

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/my-hexo-fluid/img/fluid.png">
  <link rel="icon" href="https://picgo-wskh.oss-cn-guangzhou.aliyuncs.com/avatar.jpg">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
    <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="WSKH0929">
  <meta name="keywords" content="">
  
    <meta name="description" content="1 Redis事务1.1 Redis事务简介Redis的单条命令是保证原子性的，但是redis事务不能保证原子性。 Redis事务本质：一组命令的集合。 —————– 队列 set set set 执行 ——————- 事务中每条命令都会被序列化，执行过程中按顺序执行，不允许其他命令进行干扰。  一次性 顺序性 排他性  ① Redis事务没有隔离级别的概念 ② Redis单条命令是保证原子性的，">
<meta property="og:type" content="article">
<meta property="og:title" content="Redis进阶-狂神笔记">
<meta property="og:url" content="https://wskh0929.gitee.io/2023/01/01/Redis%E8%BF%9B%E9%98%B6-%E7%8B%82%E7%A5%9E%E7%AC%94%E8%AE%B0/index.html">
<meta property="og:site_name" content="WSKH0929 的博客">
<meta property="og:description" content="1 Redis事务1.1 Redis事务简介Redis的单条命令是保证原子性的，但是redis事务不能保证原子性。 Redis事务本质：一组命令的集合。 —————– 队列 set set set 执行 ——————- 事务中每条命令都会被序列化，执行过程中按顺序执行，不允许其他命令进行干扰。  一次性 顺序性 排他性  ① Redis事务没有隔离级别的概念 ② Redis单条命令是保证原子性的，">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://picgo-wskh.oss-cn-guangzhou.aliyuncs.com/20221231155614.png">
<meta property="article:published_time" content="2023-01-01T05:42:28.000Z">
<meta property="article:modified_time" content="2022-12-31T08:00:13.729Z">
<meta property="article:author" content="WSKH0929">
<meta property="article:tag" content="KuangShen">
<meta property="article:tag" content="Java">
<meta property="article:tag" content="Redis">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://picgo-wskh.oss-cn-guangzhou.aliyuncs.com/20221231155614.png">
  
  
    <meta name="referrer" content="no-referrer-when-downgrade">
  
  
  <title>Redis进阶-狂神笔记 - WSKH0929 的博客</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/my-hexo-fluid/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/my-hexo-fluid/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/my-hexo-fluid/css/highlight-dark.css" />
  



  
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_3846514_kabxni94auf.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/shubiao.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/gundongtiao.css">



  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"wskh0929.gitee.io","root":"/my-hexo-fluid/","version":"1.9.4","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":true,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/my-hexo-fluid/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/my-hexo-fluid/js/utils.js" ></script>
  <script  src="/my-hexo-fluid/js/color-schema.js" ></script>
  

  

  

  

  

  

  

  



  
<meta name="generator" content="Hexo 5.4.2"></head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 70vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/my-hexo-fluid/">
      <strong>WSKH0929 的博客</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/my-hexo-fluid/">
                <i class="iconfont icon-home-fill"></i>
                <span>首页</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/my-hexo-fluid/archives">
                <i class="iconfont icon-books"></i>
                <span>归档</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/my-hexo-fluid/categories">
                <i class="iconfont icon-th-large"></i>
                <span>分类</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/my-hexo-fluid/tags/">
                <i class="iconfont icon-tags-fill"></i>
                <span>标签</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/my-hexo-fluid/about/">
                <i class="iconfont icon-user-fill"></i>
                <span>关于</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/my-hexo-fluid/links/">
                <i class="iconfont icon-link-fill"></i>
                <span>友链</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" target="_self" href="javascript:;" role="button"
                 data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="iconfont icon-book"></i>
                <span>文档</span>
              </a>
              <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/">
                    
                    <span>主题博客</span>
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_51545953/article/details/128499341?spm=1001.2014.3001.5501">
                    
                    <span>配置指南</span>
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/icon/">
                    
                    <span>图标用法</span>
                  </a>
                
              </div>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              <i class="iconfont icon-search"></i>
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">
              <i class="iconfont icon-dark" id="color-toggle-icon"></i>
            </a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('/my-hexo-fluid/img/default.png') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="Redis进阶-狂神笔记"></span>
          
        </div>

        
          
  <div class="mt-3">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-author" aria-hidden="true"></i>
        WSKH0929
      </span>
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2023-01-01 13:42" pubdate>
           2023 年 01 月 01 日 , 下午 01:42 , 星期日
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          <!-- compatible with older versions-->
          42k 字
        
      </span>
    

    
      <span class="post-meta mr-2">
        <i class="iconfont icon-clock-fill"></i>
        
        
        
          <!-- compatible with older versions-->
          348 分钟
        
      </span>
    

    
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      

    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">Redis进阶-狂神笔记</h1>
            
            
              <div class="markdown-body">
                
                <h1 id="1-Redis事务"><a href="#1-Redis事务" class="headerlink" title="1 Redis事务"></a>1 Redis事务</h1><h2 id="1-1-Redis事务简介"><a href="#1-1-Redis事务简介" class="headerlink" title="1.1 Redis事务简介"></a>1.1 Redis事务简介</h2><p>Redis的单条命令是保证原子性的，但是redis事务不能保证原子性。</p>
<p>Redis事务本质：一组命令的集合。</p>
<p>—————– 队列 set set set 执行 ——————-</p>
<p>事务中每条命令都会被序列化，执行过程中按顺序执行，不允许其他命令进行干扰。</p>
<ul>
<li>一次性</li>
<li>顺序性</li>
<li>排他性</li>
</ul>
<p>① Redis事务没有隔离级别的概念</p>
<p>② Redis单条命令是保证原子性的，但是事务不保证原子性！</p>
<h2 id="1-2-Redis事务操作过程"><a href="#1-2-Redis事务操作过程" class="headerlink" title="1.2 Redis事务操作过程"></a>1.2 Redis事务操作过程</h2><h3 id="1-2-1-开启事务—-gt-执行事务"><a href="#1-2-1-开启事务—-gt-执行事务" class="headerlink" title="1.2 .1 开启事务—&gt;执行事务"></a>1.2 .1 开启事务—&gt;执行事务</h3><ul>
<li>开启事务（<code>multi</code>）</li>
<li>命令入队</li>
<li>执行事务（<code>exec</code>）</li>
</ul>
<p>所有事务中的命令在加入时都没有被执行，直到提交时才会开始执行(Exec)一次性完成。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs bash">127.0.0.1:6379&gt; multi <span class="hljs-comment"># 开启事务</span><br>OK<br>127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> k1 v1 <span class="hljs-comment"># 命令入队</span><br>QUEUED<br>127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> k2 v2 <span class="hljs-comment"># ..</span><br>QUEUED<br>127.0.0.1:6379&gt; get k1<br>QUEUED<br>127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> k3 v3<br>QUEUED<br>127.0.0.1:6379&gt; keys *<br>QUEUED<br>127.0.0.1:6379&gt; <span class="hljs-built_in">exec</span> <span class="hljs-comment"># 事务执行</span><br>1) OK<br>2) OK<br>3) <span class="hljs-string">&quot;v1&quot;</span><br>4) OK<br>5) 1) <span class="hljs-string">&quot;k3&quot;</span><br>   2) <span class="hljs-string">&quot;k2&quot;</span><br>   3) <span class="hljs-string">&quot;k1&quot;</span><br></code></pre></td></tr></table></figure>

<h3 id="1-2-2-取消事务-discurd"><a href="#1-2-2-取消事务-discurd" class="headerlink" title="1.2.2 取消事务(discurd)"></a>1.2.2 <strong>取消事务(<code>discurd</code>)</strong></h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs bash">127.0.0.1:6379&gt; multi<br>OK<br>127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> k1 v1<br>QUEUED<br>127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> k2 v2<br>QUEUED<br>127.0.0.1:6379&gt; DISCARD <span class="hljs-comment"># 放弃事务</span><br>OK<br>127.0.0.1:6379&gt; EXEC <br>(error) ERR EXEC without MULTI <span class="hljs-comment"># 当前未开启事务</span><br>127.0.0.1:6379&gt; get k1 <span class="hljs-comment"># 被放弃事务中命令并未执行</span><br>(nil)<br></code></pre></td></tr></table></figure>

<h2 id="1-3-事务错误"><a href="#1-3-事务错误" class="headerlink" title="1.3 事务错误"></a>1.3 事务错误</h2><h3 id="1-3-1-编译期异常"><a href="#1-3-1-编译期异常" class="headerlink" title="1.3.1 编译期异常"></a>1.3.1 编译期异常</h3><p>代码语法错误（编译时异常）所有的命令都不执行</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs bash">127.0.0.1:6379&gt; multi<br>OK<br>127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> k1 v1<br>QUEUED<br>127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> k2 v2<br>QUEUED<br>127.0.0.1:6379&gt; error k1 <span class="hljs-comment"># 这是一条语法错误命令</span><br>(error) ERR unknown <span class="hljs-built_in">command</span> `error`, with args beginning with: `k1`, <span class="hljs-comment"># 会报错但是不影响后续命令入队 </span><br>127.0.0.1:6379&gt; get k2<br>QUEUED<br>127.0.0.1:6379&gt; EXEC<br>(error) EXECABORT Transaction discarded because of previous errors. <span class="hljs-comment"># 执行报错</span><br>127.0.0.1:6379&gt; get k1 <br>(nil) <span class="hljs-comment"># 其他命令并没有被执行</span><br></code></pre></td></tr></table></figure>

<h3 id="1-3-2-运行时异常"><a href="#1-3-2-运行时异常" class="headerlink" title="1.3.2 运行时异常"></a>1.3.2 运行时异常</h3><p>代码逻辑错误 (运行时异常) **其他命令可以正常执行 ** &gt;&gt;&gt; 所以不保证事务原子性</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs bash">127.0.0.1:6379&gt; multi<br>OK<br>127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> k1 v1<br>QUEUED<br>127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> k2 v2<br>QUEUED<br>127.0.0.1:6379&gt; INCR k1 <span class="hljs-comment"># 这条命令逻辑错误（对字符串进行增量）</span><br>QUEUED<br>127.0.0.1:6379&gt; get k2<br>QUEUED<br>127.0.0.1:6379&gt; <span class="hljs-built_in">exec</span><br>1) OK<br>2) OK<br>3) (error) ERR value is not an <span class="hljs-built_in">integer</span> or out of range <span class="hljs-comment"># 运行时报错</span><br>4) <span class="hljs-string">&quot;v2&quot;</span> <span class="hljs-comment"># 其他命令正常执行</span><br><br><span class="hljs-comment"># 虽然中间有一条命令报错了，但是后面的指令依旧正常执行成功了。</span><br><span class="hljs-comment"># 所以说Redis单条指令保证原子性，但是Redis事务不能保证原子性。</span><br></code></pre></td></tr></table></figure>

<h1 id="2-Redis实现乐观锁"><a href="#2-Redis实现乐观锁" class="headerlink" title="2 Redis实现乐观锁"></a>2 Redis实现乐观锁</h1><h2 id="2-1-乐观锁和悲观锁"><a href="#2-1-乐观锁和悲观锁" class="headerlink" title="2.1 乐观锁和悲观锁"></a>2.1 乐观锁和悲观锁</h2><p><strong>悲观锁：</strong></p>
<ul>
<li>很悲观，认为什么时候都会出现问题，无论做什么都会加锁</li>
</ul>
<p><strong>乐观锁：</strong></p>
<ul>
<li>很乐观，认为什么时候都不会出现问题，所以不会上锁！更新数据的时候去判断一下，在此期间是否有人修改过这个数据</li>
<li>获取version</li>
<li>更新的时候比较version</li>
</ul>
<p>使用<code>watch key</code>监控指定数据，相当于乐观锁加锁。</p>
<h2 id="2-2-正常执行"><a href="#2-2-正常执行" class="headerlink" title="2.2 正常执行"></a>2.2 正常执行</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs bash">127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> money 100 <span class="hljs-comment"># 设置余额:100</span><br>OK<br>127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> use 0 <span class="hljs-comment"># 支出使用:0</span><br>OK<br>127.0.0.1:6379&gt; watch money <span class="hljs-comment"># 监视money (上锁)</span><br>OK<br>127.0.0.1:6379&gt; multi<br>OK<br>127.0.0.1:6379&gt; DECRBY money 20<br>QUEUED<br>127.0.0.1:6379&gt; INCRBY use 20<br>QUEUED<br>127.0.0.1:6379&gt; <span class="hljs-built_in">exec</span> <span class="hljs-comment"># 监视值没有被中途修改，事务正常执行</span><br>1) (<span class="hljs-built_in">integer</span>) 80<br>2) (<span class="hljs-built_in">integer</span>) 20<br></code></pre></td></tr></table></figure>

<h2 id="2-3-测试异常执行"><a href="#2-3-测试异常执行" class="headerlink" title="2.3 测试异常执行"></a>2.3 测试异常执行</h2><p>测试多线程修改值，使用watch可以当做redis的乐观锁操作（相当于getversion）</p>
<p>我们启动另外一个客户端模拟插队线程。</p>
<p>线程1：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash">127.0.0.1:6379&gt; watch money <span class="hljs-comment"># money上锁</span><br>OK<br>127.0.0.1:6379&gt; multi<br>OK<br>127.0.0.1:6379&gt; DECRBY money 20<br>QUEUED<br>127.0.0.1:6379&gt; INCRBY use 20<br>QUEUED<br>127.0.0.1:6379&gt; 	<span class="hljs-comment"># 此时事务并没有执行</span><br></code></pre></td></tr></table></figure>

<p>模拟线程插队，线程2：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">127.0.0.1:6379&gt; INCRBY money 500 <span class="hljs-comment"># 修改了线程一中监视的money</span><br>(<span class="hljs-built_in">integer</span>) 600<br></code></pre></td></tr></table></figure>

<p>回到线程1，执行事务：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash">127.0.0.1:6379&gt; EXEC <span class="hljs-comment"># 执行之前，另一个线程修改了我们的值，这个时候就会导致事务执行失败</span><br>(nil) <span class="hljs-comment"># 没有结果，说明事务执行失败</span><br><br>127.0.0.1:6379&gt; get money <span class="hljs-comment"># 线程2 修改生效</span><br><span class="hljs-string">&quot;600&quot;</span><br>127.0.0.1:6379&gt; get use <span class="hljs-comment"># 线程1事务执行失败，数值没有被修改</span><br><span class="hljs-string">&quot;0&quot;</span><br></code></pre></td></tr></table></figure>

<p>解锁获取最新值，然后再加锁进行事务。</p>
<p><code>unwatch</code>进行解锁。</p>
<p>== 注意：每次提交执行exec后都会自动释放锁，不管是否成功 ==</p>
<h1 id="3-Jedis"><a href="#3-Jedis" class="headerlink" title="3  Jedis"></a>3  Jedis</h1><h2 id="3-1-导入依赖"><a href="#3-1-导入依赖" class="headerlink" title="3.1 导入依赖"></a>3.1 导入依赖</h2><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>        <span class="hljs-comment">&lt;!--导入jredis的包--&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>redis.clients<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>jedis<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.3.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-comment">&lt;!--fastjson--&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.alibaba<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>fastjson<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.2.75<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h2 id="3-2-编码测试"><a href="#3-2-编码测试" class="headerlink" title="3.2 编码测试"></a>3.2 编码测试</h2><h3 id="3-2-1-修改配置文件"><a href="#3-2-1-修改配置文件" class="headerlink" title="3.2.1 修改配置文件"></a>3.2.1 修改配置文件</h3><p>(不修改可能会报错，修改一次一劳永逸)</p>
<p>注释掉bind，protected-mode为no</p>
<p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831145247.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p>查看远程服务器的防火墙状态</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">systemctl status firewalld<br></code></pre></td></tr></table></figure>

<p>如果为开启状态，执行以下代码：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment">#查看防火墙状态</span><br>firewall-cmd --state<br><br><span class="hljs-comment">#开放6379端口</span><br>firewall-cmd --permanent --add-port=6379/tcp<br><span class="hljs-comment">#查看端口，执行</span><br>firewall-cmd --permanent --query-port=6379/tcp<br><br>firewall-cmd --permanent --list-ports<br><span class="hljs-comment">#重启防火墙</span><br>firewall-cmd --reload<br></code></pre></td></tr></table></figure>

<p>执行完上面代码或者防火墙未开启，继续执行下面代码：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">redis-cli -p 6379 shutdown<br>redis-server redis_config/redis.conf<br>redis-cli -p 6379<br></code></pre></td></tr></table></figure>

<p>测试一下是否可以连接成功:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TestPing</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Jedis</span> <span class="hljs-variable">jedis</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Jedis</span>(<span class="hljs-string">&quot;120.79.99.207&quot;</span>,<span class="hljs-number">6379</span>);<br>        System.out.println(jedis.ping());<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831145336.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="3-3-常用API"><a href="#3-3-常用API" class="headerlink" title="3.3 常用API"></a>3.3 常用API</h2><p>（需要时可以百度查,和原生redisAPI非常相似）</p>
<p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831144839.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h1 id="4-Jedis实现事务操作"><a href="#4-Jedis实现事务操作" class="headerlink" title="4 Jedis实现事务操作"></a>4 Jedis实现事务操作</h1><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TestTX</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Jedis</span> <span class="hljs-variable">jedis</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Jedis</span>(<span class="hljs-string">&quot;120.79.99.207&quot;</span>, <span class="hljs-number">6379</span>);<br><br>        jedis.flushDB();<br><br>        <span class="hljs-type">JSONObject</span> <span class="hljs-variable">jsonObject</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">JSONObject</span>();<br>        jsonObject.put(<span class="hljs-string">&quot;hello&quot;</span>, <span class="hljs-string">&quot;world&quot;</span>);<br>        jsonObject.put(<span class="hljs-string">&quot;name&quot;</span>, <span class="hljs-string">&quot;wskh&quot;</span>);<br>        <span class="hljs-comment">// 开启事务</span><br>        <span class="hljs-type">Transaction</span> <span class="hljs-variable">multi</span> <span class="hljs-operator">=</span> jedis.multi();<br>        <span class="hljs-type">String</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> jsonObject.toJSONString();<br>        <span class="hljs-comment">// 乐观锁</span><br>        <span class="hljs-comment">// jedis.watch(result);</span><br>        <span class="hljs-keyword">try</span> &#123;<br>            multi.set(<span class="hljs-string">&quot;user1&quot;</span>, result);<br>            multi.set(<span class="hljs-string">&quot;user2&quot;</span>, result);<br>            <span class="hljs-comment">// 事务成功，执行事务</span><br>            multi.exec();<br>        &#125;<span class="hljs-keyword">catch</span> (Exception e)&#123;<br>            <span class="hljs-comment">// 事务失败，放弃事务</span><br>            multi.discard();<br>        &#125; <span class="hljs-keyword">finally</span> &#123;<br>            <span class="hljs-comment">// 最后，关闭连接</span><br>            System.out.println(jedis.get(<span class="hljs-string">&quot;user1&quot;</span>));<br>            System.out.println(jedis.get(<span class="hljs-string">&quot;user2&quot;</span>));<br>            jedis.close();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="5-SpringBoot集成Jedis"><a href="#5-SpringBoot集成Jedis" class="headerlink" title="5 SpringBoot集成Jedis"></a>5 SpringBoot集成Jedis</h1><h2 id="5-1-新建springboot项目"><a href="#5-1-新建springboot项目" class="headerlink" title="5.1 新建springboot项目"></a>5.1 新建springboot项目</h2><p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831145400.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831145405.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831145500.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="5-2-源码分析"><a href="#5-2-源码分析" class="headerlink" title="5.2 源码分析"></a>5.2 源码分析</h2><p>springboot 2.x后 ，原来使用的 Jedis 被 lettuce 替换。</p>
<p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831145759.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831145733.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831145759.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="5-3-配置redis"><a href="#5-3-配置redis" class="headerlink" title="5.3 配置redis"></a>5.3 配置redis</h2><p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831145846.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"># 配置redis<br>spring.redis.host= <span class="hljs-number">120.79</span><span class="hljs-number">.99</span><span class="hljs-number">.207</span><br>spring.redis.port= <span class="hljs-number">6379</span><br></code></pre></td></tr></table></figure>

<h2 id="5-4-测试一下"><a href="#5-4-测试一下" class="headerlink" title="5.4 测试一下"></a>5.4 测试一下</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@SpringBootTest</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">RedisSpringbootApplicationTests</span> &#123;<br><br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> RedisTemplate redisTemplate;<br><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-keyword">void</span> <span class="hljs-title function_">contextLoads</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-comment">// redisTemplate 操作不同的数据类型，api和我们的指令是一样的</span><br>        <span class="hljs-comment">// opsForValue 操作字符串 类似String</span><br>        <span class="hljs-comment">// opsForList 操作List 类似List</span><br>        <span class="hljs-comment">// opsForHash</span><br>        <span class="hljs-comment">// opsForZSet</span><br>        <span class="hljs-comment">// opsForGeo</span><br>        <span class="hljs-comment">// opsForHyperLogLog</span><br><br>        <span class="hljs-comment">// 除了基本的操作，我们常用的方法都可以直接通过redisTemplate操作，比如事务和基本的CRUD</span><br><br>        <span class="hljs-comment">// 获取连接对象</span><br>        <span class="hljs-comment">//RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();</span><br>        <span class="hljs-comment">//connection.flushDb();</span><br>        <span class="hljs-comment">//connection.flushAll();</span><br><br>        redisTemplate.opsForValue().set(<span class="hljs-string">&quot;mykey&quot;</span>,<span class="hljs-string">&quot;王孙康宏&quot;</span>);<br>        System.out.println(redisTemplate.opsForValue().get(<span class="hljs-string">&quot;mykey&quot;</span>));<br>    &#125;<br><br>&#125;<br></code></pre></td></tr></table></figure>

<p>测试结果：</p>
<p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831145902.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p>成功~~~</p>
<h2 id="5-5-序列化解决中文乱码问题"><a href="#5-5-序列化解决中文乱码问题" class="headerlink" title="5.5 序列化解决中文乱码问题"></a>5.5 序列化解决中文乱码问题</h2><p>如果直接用jedis提供的api进行存储是不能存储中文的，会出现乱码问题。所以我们需要通过序列化的手段解决中文乱码问题</p>
<p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/image-20210831213029800.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload alt="image-20210831213029800"></p>
<h2 id="5-6-Jedis工具类"><a href="#5-6-Jedis工具类" class="headerlink" title="5.6  Jedis工具类"></a>5.6  Jedis工具类</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br><span class="line">512</span><br><span class="line">513</span><br><span class="line">514</span><br><span class="line">515</span><br><span class="line">516</span><br><span class="line">517</span><br><span class="line">518</span><br><span class="line">519</span><br><span class="line">520</span><br><span class="line">521</span><br><span class="line">522</span><br><span class="line">523</span><br><span class="line">524</span><br><span class="line">525</span><br><span class="line">526</span><br><span class="line">527</span><br><span class="line">528</span><br><span class="line">529</span><br><span class="line">530</span><br><span class="line">531</span><br><span class="line">532</span><br><span class="line">533</span><br><span class="line">534</span><br><span class="line">535</span><br><span class="line">536</span><br><span class="line">537</span><br><span class="line">538</span><br><span class="line">539</span><br><span class="line">540</span><br><span class="line">541</span><br><span class="line">542</span><br><span class="line">543</span><br><span class="line">544</span><br><span class="line">545</span><br><span class="line">546</span><br><span class="line">547</span><br><span class="line">548</span><br><span class="line">549</span><br><span class="line">550</span><br><span class="line">551</span><br><span class="line">552</span><br><span class="line">553</span><br><span class="line">554</span><br><span class="line">555</span><br><span class="line">556</span><br><span class="line">557</span><br><span class="line">558</span><br><span class="line">559</span><br><span class="line">560</span><br><span class="line">561</span><br><span class="line">562</span><br><span class="line">563</span><br><span class="line">564</span><br><span class="line">565</span><br><span class="line">566</span><br><span class="line">567</span><br><span class="line">568</span><br><span class="line">569</span><br><span class="line">570</span><br><span class="line">571</span><br><span class="line">572</span><br><span class="line">573</span><br><span class="line">574</span><br><span class="line">575</span><br><span class="line">576</span><br><span class="line">577</span><br><span class="line">578</span><br><span class="line">579</span><br><span class="line">580</span><br><span class="line">581</span><br><span class="line">582</span><br><span class="line">583</span><br><span class="line">584</span><br><span class="line">585</span><br><span class="line">586</span><br><span class="line">587</span><br><span class="line">588</span><br><span class="line">589</span><br><span class="line">590</span><br><span class="line">591</span><br><span class="line">592</span><br><span class="line">593</span><br><span class="line">594</span><br><span class="line">595</span><br><span class="line">596</span><br><span class="line">597</span><br><span class="line">598</span><br><span class="line">599</span><br><span class="line">600</span><br><span class="line">601</span><br><span class="line">602</span><br><span class="line">603</span><br><span class="line">604</span><br><span class="line">605</span><br><span class="line">606</span><br><span class="line">607</span><br><span class="line">608</span><br><span class="line">609</span><br><span class="line">610</span><br><span class="line">611</span><br><span class="line">612</span><br><span class="line">613</span><br><span class="line">614</span><br><span class="line">615</span><br><span class="line">616</span><br><span class="line">617</span><br><span class="line">618</span><br><span class="line">619</span><br><span class="line">620</span><br><span class="line">621</span><br><span class="line">622</span><br><span class="line">623</span><br><span class="line">624</span><br><span class="line">625</span><br><span class="line">626</span><br><span class="line">627</span><br><span class="line">628</span><br><span class="line">629</span><br><span class="line">630</span><br><span class="line">631</span><br><span class="line">632</span><br><span class="line">633</span><br><span class="line">634</span><br><span class="line">635</span><br><span class="line">636</span><br><span class="line">637</span><br><span class="line">638</span><br><span class="line">639</span><br><span class="line">640</span><br><span class="line">641</span><br><span class="line">642</span><br><span class="line">643</span><br><span class="line">644</span><br><span class="line">645</span><br><span class="line">646</span><br><span class="line">647</span><br><span class="line">648</span><br><span class="line">649</span><br><span class="line">650</span><br><span class="line">651</span><br><span class="line">652</span><br><span class="line">653</span><br><span class="line">654</span><br><span class="line">655</span><br><span class="line">656</span><br><span class="line">657</span><br><span class="line">658</span><br><span class="line">659</span><br><span class="line">660</span><br><span class="line">661</span><br><span class="line">662</span><br><span class="line">663</span><br><span class="line">664</span><br><span class="line">665</span><br><span class="line">666</span><br><span class="line">667</span><br><span class="line">668</span><br><span class="line">669</span><br><span class="line">670</span><br><span class="line">671</span><br><span class="line">672</span><br><span class="line">673</span><br><span class="line">674</span><br><span class="line">675</span><br><span class="line">676</span><br><span class="line">677</span><br><span class="line">678</span><br><span class="line">679</span><br><span class="line">680</span><br><span class="line">681</span><br><span class="line">682</span><br><span class="line">683</span><br><span class="line">684</span><br><span class="line">685</span><br><span class="line">686</span><br><span class="line">687</span><br><span class="line">688</span><br><span class="line">689</span><br><span class="line">690</span><br><span class="line">691</span><br><span class="line">692</span><br><span class="line">693</span><br><span class="line">694</span><br><span class="line">695</span><br><span class="line">696</span><br><span class="line">697</span><br><span class="line">698</span><br><span class="line">699</span><br><span class="line">700</span><br><span class="line">701</span><br><span class="line">702</span><br><span class="line">703</span><br><span class="line">704</span><br><span class="line">705</span><br><span class="line">706</span><br><span class="line">707</span><br><span class="line">708</span><br><span class="line">709</span><br><span class="line">710</span><br><span class="line">711</span><br><span class="line">712</span><br><span class="line">713</span><br><span class="line">714</span><br><span class="line">715</span><br><span class="line">716</span><br><span class="line">717</span><br><span class="line">718</span><br><span class="line">719</span><br><span class="line">720</span><br><span class="line">721</span><br><span class="line">722</span><br><span class="line">723</span><br><span class="line">724</span><br><span class="line">725</span><br><span class="line">726</span><br><span class="line">727</span><br><span class="line">728</span><br><span class="line">729</span><br><span class="line">730</span><br><span class="line">731</span><br><span class="line">732</span><br><span class="line">733</span><br><span class="line">734</span><br><span class="line">735</span><br><span class="line">736</span><br><span class="line">737</span><br><span class="line">738</span><br><span class="line">739</span><br><span class="line">740</span><br><span class="line">741</span><br><span class="line">742</span><br><span class="line">743</span><br><span class="line">744</span><br><span class="line">745</span><br><span class="line">746</span><br><span class="line">747</span><br><span class="line">748</span><br><span class="line">749</span><br><span class="line">750</span><br><span class="line">751</span><br><span class="line">752</span><br><span class="line">753</span><br><span class="line">754</span><br><span class="line">755</span><br><span class="line">756</span><br><span class="line">757</span><br><span class="line">758</span><br><span class="line">759</span><br><span class="line">760</span><br><span class="line">761</span><br><span class="line">762</span><br><span class="line">763</span><br><span class="line">764</span><br><span class="line">765</span><br><span class="line">766</span><br><span class="line">767</span><br><span class="line">768</span><br><span class="line">769</span><br><span class="line">770</span><br><span class="line">771</span><br><span class="line">772</span><br><span class="line">773</span><br><span class="line">774</span><br><span class="line">775</span><br><span class="line">776</span><br><span class="line">777</span><br><span class="line">778</span><br><span class="line">779</span><br><span class="line">780</span><br><span class="line">781</span><br><span class="line">782</span><br><span class="line">783</span><br><span class="line">784</span><br><span class="line">785</span><br><span class="line">786</span><br><span class="line">787</span><br><span class="line">788</span><br><span class="line">789</span><br><span class="line">790</span><br><span class="line">791</span><br><span class="line">792</span><br><span class="line">793</span><br><span class="line">794</span><br><span class="line">795</span><br><span class="line">796</span><br><span class="line">797</span><br><span class="line">798</span><br><span class="line">799</span><br><span class="line">800</span><br><span class="line">801</span><br><span class="line">802</span><br><span class="line">803</span><br><span class="line">804</span><br><span class="line">805</span><br><span class="line">806</span><br><span class="line">807</span><br><span class="line">808</span><br><span class="line">809</span><br><span class="line">810</span><br><span class="line">811</span><br><span class="line">812</span><br><span class="line">813</span><br><span class="line">814</span><br><span class="line">815</span><br><span class="line">816</span><br><span class="line">817</span><br><span class="line">818</span><br><span class="line">819</span><br><span class="line">820</span><br><span class="line">821</span><br><span class="line">822</span><br><span class="line">823</span><br><span class="line">824</span><br><span class="line">825</span><br><span class="line">826</span><br><span class="line">827</span><br><span class="line">828</span><br><span class="line">829</span><br><span class="line">830</span><br><span class="line">831</span><br><span class="line">832</span><br><span class="line">833</span><br><span class="line">834</span><br><span class="line">835</span><br><span class="line">836</span><br><span class="line">837</span><br><span class="line">838</span><br><span class="line">839</span><br><span class="line">840</span><br><span class="line">841</span><br><span class="line">842</span><br><span class="line">843</span><br><span class="line">844</span><br><span class="line">845</span><br><span class="line">846</span><br><span class="line">847</span><br><span class="line">848</span><br><span class="line">849</span><br><span class="line">850</span><br><span class="line">851</span><br><span class="line">852</span><br><span class="line">853</span><br><span class="line">854</span><br><span class="line">855</span><br><span class="line">856</span><br><span class="line">857</span><br><span class="line">858</span><br><span class="line">859</span><br><span class="line">860</span><br><span class="line">861</span><br><span class="line">862</span><br><span class="line">863</span><br><span class="line">864</span><br><span class="line">865</span><br><span class="line">866</span><br><span class="line">867</span><br><span class="line">868</span><br><span class="line">869</span><br><span class="line">870</span><br><span class="line">871</span><br><span class="line">872</span><br><span class="line">873</span><br><span class="line">874</span><br><span class="line">875</span><br><span class="line">876</span><br><span class="line">877</span><br><span class="line">878</span><br><span class="line">879</span><br><span class="line">880</span><br><span class="line">881</span><br><span class="line">882</span><br><span class="line">883</span><br><span class="line">884</span><br><span class="line">885</span><br><span class="line">886</span><br><span class="line">887</span><br><span class="line">888</span><br><span class="line">889</span><br><span class="line">890</span><br><span class="line">891</span><br><span class="line">892</span><br><span class="line">893</span><br><span class="line">894</span><br><span class="line">895</span><br><span class="line">896</span><br><span class="line">897</span><br><span class="line">898</span><br><span class="line">899</span><br><span class="line">900</span><br><span class="line">901</span><br><span class="line">902</span><br><span class="line">903</span><br><span class="line">904</span><br><span class="line">905</span><br><span class="line">906</span><br><span class="line">907</span><br><span class="line">908</span><br><span class="line">909</span><br><span class="line">910</span><br><span class="line">911</span><br><span class="line">912</span><br><span class="line">913</span><br><span class="line">914</span><br><span class="line">915</span><br><span class="line">916</span><br><span class="line">917</span><br><span class="line">918</span><br><span class="line">919</span><br><span class="line">920</span><br><span class="line">921</span><br><span class="line">922</span><br><span class="line">923</span><br><span class="line">924</span><br><span class="line">925</span><br><span class="line">926</span><br><span class="line">927</span><br><span class="line">928</span><br><span class="line">929</span><br><span class="line">930</span><br><span class="line">931</span><br><span class="line">932</span><br><span class="line">933</span><br><span class="line">934</span><br><span class="line">935</span><br><span class="line">936</span><br><span class="line">937</span><br><span class="line">938</span><br><span class="line">939</span><br><span class="line">940</span><br><span class="line">941</span><br><span class="line">942</span><br><span class="line">943</span><br><span class="line">944</span><br><span class="line">945</span><br><span class="line">946</span><br><span class="line">947</span><br><span class="line">948</span><br><span class="line">949</span><br><span class="line">950</span><br><span class="line">951</span><br><span class="line">952</span><br><span class="line">953</span><br><span class="line">954</span><br><span class="line">955</span><br><span class="line">956</span><br><span class="line">957</span><br><span class="line">958</span><br><span class="line">959</span><br><span class="line">960</span><br><span class="line">961</span><br><span class="line">962</span><br><span class="line">963</span><br><span class="line">964</span><br><span class="line">965</span><br><span class="line">966</span><br><span class="line">967</span><br><span class="line">968</span><br><span class="line">969</span><br><span class="line">970</span><br><span class="line">971</span><br><span class="line">972</span><br><span class="line">973</span><br><span class="line">974</span><br><span class="line">975</span><br><span class="line">976</span><br><span class="line">977</span><br><span class="line">978</span><br><span class="line">979</span><br><span class="line">980</span><br><span class="line">981</span><br><span class="line">982</span><br><span class="line">983</span><br><span class="line">984</span><br><span class="line">985</span><br><span class="line">986</span><br><span class="line">987</span><br><span class="line">988</span><br><span class="line">989</span><br><span class="line">990</span><br><span class="line">991</span><br><span class="line">992</span><br><span class="line">993</span><br><span class="line">994</span><br><span class="line">995</span><br><span class="line">996</span><br><span class="line">997</span><br><span class="line">998</span><br><span class="line">999</span><br><span class="line">1000</span><br><span class="line">1001</span><br><span class="line">1002</span><br><span class="line">1003</span><br><span class="line">1004</span><br><span class="line">1005</span><br><span class="line">1006</span><br><span class="line">1007</span><br><span class="line">1008</span><br><span class="line">1009</span><br><span class="line">1010</span><br><span class="line">1011</span><br><span class="line">1012</span><br><span class="line">1013</span><br><span class="line">1014</span><br><span class="line">1015</span><br><span class="line">1016</span><br><span class="line">1017</span><br><span class="line">1018</span><br><span class="line">1019</span><br><span class="line">1020</span><br><span class="line">1021</span><br><span class="line">1022</span><br><span class="line">1023</span><br><span class="line">1024</span><br><span class="line">1025</span><br><span class="line">1026</span><br><span class="line">1027</span><br><span class="line">1028</span><br><span class="line">1029</span><br><span class="line">1030</span><br><span class="line">1031</span><br><span class="line">1032</span><br><span class="line">1033</span><br><span class="line">1034</span><br><span class="line">1035</span><br><span class="line">1036</span><br><span class="line">1037</span><br><span class="line">1038</span><br><span class="line">1039</span><br><span class="line">1040</span><br><span class="line">1041</span><br><span class="line">1042</span><br><span class="line">1043</span><br><span class="line">1044</span><br><span class="line">1045</span><br><span class="line">1046</span><br><span class="line">1047</span><br><span class="line">1048</span><br><span class="line">1049</span><br><span class="line">1050</span><br><span class="line">1051</span><br><span class="line">1052</span><br><span class="line">1053</span><br><span class="line">1054</span><br><span class="line">1055</span><br><span class="line">1056</span><br><span class="line">1057</span><br><span class="line">1058</span><br><span class="line">1059</span><br><span class="line">1060</span><br><span class="line">1061</span><br><span class="line">1062</span><br><span class="line">1063</span><br><span class="line">1064</span><br><span class="line">1065</span><br><span class="line">1066</span><br><span class="line">1067</span><br><span class="line">1068</span><br><span class="line">1069</span><br><span class="line">1070</span><br><span class="line">1071</span><br><span class="line">1072</span><br><span class="line">1073</span><br><span class="line">1074</span><br><span class="line">1075</span><br><span class="line">1076</span><br><span class="line">1077</span><br><span class="line">1078</span><br><span class="line">1079</span><br><span class="line">1080</span><br><span class="line">1081</span><br><span class="line">1082</span><br><span class="line">1083</span><br><span class="line">1084</span><br><span class="line">1085</span><br><span class="line">1086</span><br><span class="line">1087</span><br><span class="line">1088</span><br><span class="line">1089</span><br><span class="line">1090</span><br><span class="line">1091</span><br><span class="line">1092</span><br><span class="line">1093</span><br><span class="line">1094</span><br><span class="line">1095</span><br><span class="line">1096</span><br><span class="line">1097</span><br><span class="line">1098</span><br><span class="line">1099</span><br><span class="line">1100</span><br><span class="line">1101</span><br><span class="line">1102</span><br><span class="line">1103</span><br><span class="line">1104</span><br><span class="line">1105</span><br><span class="line">1106</span><br><span class="line">1107</span><br><span class="line">1108</span><br><span class="line">1109</span><br><span class="line">1110</span><br><span class="line">1111</span><br><span class="line">1112</span><br><span class="line">1113</span><br><span class="line">1114</span><br><span class="line">1115</span><br><span class="line">1116</span><br><span class="line">1117</span><br><span class="line">1118</span><br><span class="line">1119</span><br><span class="line">1120</span><br><span class="line">1121</span><br><span class="line">1122</span><br><span class="line">1123</span><br><span class="line">1124</span><br><span class="line">1125</span><br><span class="line">1126</span><br><span class="line">1127</span><br><span class="line">1128</span><br><span class="line">1129</span><br><span class="line">1130</span><br><span class="line">1131</span><br><span class="line">1132</span><br><span class="line">1133</span><br><span class="line">1134</span><br><span class="line">1135</span><br><span class="line">1136</span><br><span class="line">1137</span><br><span class="line">1138</span><br><span class="line">1139</span><br><span class="line">1140</span><br><span class="line">1141</span><br><span class="line">1142</span><br><span class="line">1143</span><br><span class="line">1144</span><br><span class="line">1145</span><br><span class="line">1146</span><br><span class="line">1147</span><br><span class="line">1148</span><br><span class="line">1149</span><br><span class="line">1150</span><br><span class="line">1151</span><br><span class="line">1152</span><br><span class="line">1153</span><br><span class="line">1154</span><br><span class="line">1155</span><br><span class="line">1156</span><br><span class="line">1157</span><br><span class="line">1158</span><br><span class="line">1159</span><br><span class="line">1160</span><br><span class="line">1161</span><br><span class="line">1162</span><br><span class="line">1163</span><br><span class="line">1164</span><br><span class="line">1165</span><br><span class="line">1166</span><br><span class="line">1167</span><br><span class="line">1168</span><br><span class="line">1169</span><br><span class="line">1170</span><br><span class="line">1171</span><br><span class="line">1172</span><br><span class="line">1173</span><br><span class="line">1174</span><br><span class="line">1175</span><br><span class="line">1176</span><br><span class="line">1177</span><br><span class="line">1178</span><br><span class="line">1179</span><br><span class="line">1180</span><br><span class="line">1181</span><br><span class="line">1182</span><br><span class="line">1183</span><br><span class="line">1184</span><br><span class="line">1185</span><br><span class="line">1186</span><br><span class="line">1187</span><br><span class="line">1188</span><br><span class="line">1189</span><br><span class="line">1190</span><br><span class="line">1191</span><br><span class="line">1192</span><br><span class="line">1193</span><br><span class="line">1194</span><br><span class="line">1195</span><br><span class="line">1196</span><br><span class="line">1197</span><br><span class="line">1198</span><br><span class="line">1199</span><br><span class="line">1200</span><br><span class="line">1201</span><br><span class="line">1202</span><br><span class="line">1203</span><br><span class="line">1204</span><br><span class="line">1205</span><br><span class="line">1206</span><br><span class="line">1207</span><br><span class="line">1208</span><br><span class="line">1209</span><br><span class="line">1210</span><br><span class="line">1211</span><br><span class="line">1212</span><br><span class="line">1213</span><br><span class="line">1214</span><br><span class="line">1215</span><br><span class="line">1216</span><br><span class="line">1217</span><br><span class="line">1218</span><br><span class="line">1219</span><br><span class="line">1220</span><br><span class="line">1221</span><br><span class="line">1222</span><br><span class="line">1223</span><br><span class="line">1224</span><br><span class="line">1225</span><br><span class="line">1226</span><br><span class="line">1227</span><br><span class="line">1228</span><br><span class="line">1229</span><br><span class="line">1230</span><br><span class="line">1231</span><br><span class="line">1232</span><br><span class="line">1233</span><br><span class="line">1234</span><br><span class="line">1235</span><br><span class="line">1236</span><br><span class="line">1237</span><br><span class="line">1238</span><br><span class="line">1239</span><br><span class="line">1240</span><br><span class="line">1241</span><br><span class="line">1242</span><br><span class="line">1243</span><br><span class="line">1244</span><br><span class="line">1245</span><br><span class="line">1246</span><br><span class="line">1247</span><br><span class="line">1248</span><br><span class="line">1249</span><br><span class="line">1250</span><br><span class="line">1251</span><br><span class="line">1252</span><br><span class="line">1253</span><br><span class="line">1254</span><br><span class="line">1255</span><br><span class="line">1256</span><br><span class="line">1257</span><br><span class="line">1258</span><br><span class="line">1259</span><br><span class="line">1260</span><br><span class="line">1261</span><br><span class="line">1262</span><br><span class="line">1263</span><br><span class="line">1264</span><br><span class="line">1265</span><br><span class="line">1266</span><br><span class="line">1267</span><br><span class="line">1268</span><br><span class="line">1269</span><br><span class="line">1270</span><br><span class="line">1271</span><br><span class="line">1272</span><br><span class="line">1273</span><br><span class="line">1274</span><br><span class="line">1275</span><br><span class="line">1276</span><br><span class="line">1277</span><br><span class="line">1278</span><br><span class="line">1279</span><br><span class="line">1280</span><br><span class="line">1281</span><br><span class="line">1282</span><br><span class="line">1283</span><br><span class="line">1284</span><br><span class="line">1285</span><br><span class="line">1286</span><br><span class="line">1287</span><br><span class="line">1288</span><br><span class="line">1289</span><br><span class="line">1290</span><br><span class="line">1291</span><br><span class="line">1292</span><br><span class="line">1293</span><br><span class="line">1294</span><br><span class="line">1295</span><br><span class="line">1296</span><br><span class="line">1297</span><br><span class="line">1298</span><br><span class="line">1299</span><br><span class="line">1300</span><br><span class="line">1301</span><br><span class="line">1302</span><br><span class="line">1303</span><br><span class="line">1304</span><br><span class="line">1305</span><br><span class="line">1306</span><br><span class="line">1307</span><br><span class="line">1308</span><br><span class="line">1309</span><br><span class="line">1310</span><br><span class="line">1311</span><br><span class="line">1312</span><br><span class="line">1313</span><br><span class="line">1314</span><br><span class="line">1315</span><br><span class="line">1316</span><br><span class="line">1317</span><br><span class="line">1318</span><br><span class="line">1319</span><br><span class="line">1320</span><br><span class="line">1321</span><br><span class="line">1322</span><br><span class="line">1323</span><br><span class="line">1324</span><br><span class="line">1325</span><br><span class="line">1326</span><br><span class="line">1327</span><br><span class="line">1328</span><br><span class="line">1329</span><br><span class="line">1330</span><br><span class="line">1331</span><br><span class="line">1332</span><br><span class="line">1333</span><br><span class="line">1334</span><br><span class="line">1335</span><br><span class="line">1336</span><br><span class="line">1337</span><br><span class="line">1338</span><br><span class="line">1339</span><br><span class="line">1340</span><br><span class="line">1341</span><br><span class="line">1342</span><br><span class="line">1343</span><br><span class="line">1344</span><br><span class="line">1345</span><br><span class="line">1346</span><br><span class="line">1347</span><br><span class="line">1348</span><br><span class="line">1349</span><br><span class="line">1350</span><br><span class="line">1351</span><br><span class="line">1352</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">import</span> org.springframework.data.redis.connection.DataType;<br><span class="hljs-keyword">import</span> org.springframework.data.redis.core.Cursor;<br><span class="hljs-keyword">import</span> org.springframework.data.redis.core.ScanOptions;<br><span class="hljs-keyword">import</span> org.springframework.data.redis.core.StringRedisTemplate;<br><span class="hljs-keyword">import</span> org.springframework.data.redis.core.ZSetOperations.TypedTuple;<br><br><span class="hljs-keyword">import</span> java.util.Collection;<br><span class="hljs-keyword">import</span> java.util.Date;<br><span class="hljs-keyword">import</span> java.util.List;<br><span class="hljs-keyword">import</span> java.util.Map;<br><span class="hljs-keyword">import</span> java.util.Map.Entry;<br><span class="hljs-keyword">import</span> java.util.Set;<br><span class="hljs-keyword">import</span> java.util.concurrent.TimeUnit;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * Redis工具类*/</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">RedisUtil</span> &#123;<br>    <span class="hljs-keyword">private</span> StringRedisTemplate redisTemplate;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setRedisTemplate</span><span class="hljs-params">(StringRedisTemplate redisTemplate)</span> &#123;<br>        <span class="hljs-built_in">this</span>.redisTemplate = redisTemplate;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> StringRedisTemplate <span class="hljs-title function_">getRedisTemplate</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.redisTemplate;<br>    &#125;<br><br>    <span class="hljs-comment">/** -------------------key相关操作--------------------- */</span><br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 删除key</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">delete</span><span class="hljs-params">(String key)</span> &#123;<br>        redisTemplate.delete(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 批量删除key</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> keys</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">delete</span><span class="hljs-params">(Collection&lt;String&gt; keys)</span> &#123;<br>        redisTemplate.delete(keys);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 序列化key</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">byte</span>[] dump(String key) &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.dump(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 是否存在key</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Boolean <span class="hljs-title function_">hasKey</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.hasKey(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 设置过期时间</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> timeout</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> unit</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Boolean <span class="hljs-title function_">expire</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> timeout, TimeUnit unit)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.expire(key, timeout, unit);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 设置过期时间</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> date</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Boolean <span class="hljs-title function_">expireAt</span><span class="hljs-params">(String key, Date date)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.expireAt(key, date);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 查找匹配的key</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> pattern</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">keys</span><span class="hljs-params">(String pattern)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.keys(pattern);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 将当前数据库的 key 移动到给定的数据库 db 当中</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> dbIndex</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Boolean <span class="hljs-title function_">move</span><span class="hljs-params">(String key, <span class="hljs-type">int</span> dbIndex)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.move(key, dbIndex);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 移除 key 的过期时间，key 将持久保持</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Boolean <span class="hljs-title function_">persist</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.persist(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 返回 key 的剩余的过期时间</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> unit</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">getExpire</span><span class="hljs-params">(String key, TimeUnit unit)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.getExpire(key, unit);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 返回 key 的剩余的过期时间</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">getExpire</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.getExpire(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 从当前数据库中随机返回一个 key</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">randomKey</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.randomKey();<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 修改 key 的名称</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> oldKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> newKey</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">rename</span><span class="hljs-params">(String oldKey, String newKey)</span> &#123;<br>        redisTemplate.rename(oldKey, newKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 仅当 newkey 不存在时，将 oldKey 改名为 newkey</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> oldKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> newKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Boolean <span class="hljs-title function_">renameIfAbsent</span><span class="hljs-params">(String oldKey, String newKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.renameIfAbsent(oldKey, newKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 返回 key 所储存的值的类型</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> DataType <span class="hljs-title function_">type</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.type(key);<br>    &#125;<br><br>    <span class="hljs-comment">/** -------------------string相关操作--------------------- */</span><br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 设置指定 key 的值</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">set</span><span class="hljs-params">(String key, String value)</span> &#123;<br>        redisTemplate.opsForValue().set(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取指定 key 的值</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">get</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForValue().get(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 返回 key 中字符串值的子字符</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> start</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> end</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getRange</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> start, <span class="hljs-type">long</span> end)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForValue().get(key, start, end);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 将给定 key 的值设为 value ，并返回 key 的旧值(old value)</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getAndSet</span><span class="hljs-params">(String key, String value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForValue().getAndSet(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 对 key 所储存的字符串值，获取指定偏移量上的位(bit)</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> offset</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Boolean <span class="hljs-title function_">getBit</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> offset)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForValue().getBit(key, offset);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 批量获取</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> keys</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> List&lt;String&gt; <span class="hljs-title function_">multiGet</span><span class="hljs-params">(Collection&lt;String&gt; keys)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForValue().multiGet(keys);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 设置ASCII码, 字符串&#x27;a&#x27;的ASCII码是97, 转为二进制是&#x27;01100001&#x27;, 此方法是将二进制第offset位值变为value</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key 位置</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     *            值,true为1, false为0</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">setBit</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> offset, <span class="hljs-type">boolean</span> value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForValue().setBit(key, offset, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 将值 value 关联到 key ，并将 key 的过期时间设为 timeout</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> timeout</span><br><span class="hljs-comment">     *            过期时间</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> unit</span><br><span class="hljs-comment">     *            时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES</span><br><span class="hljs-comment">     *            秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setEx</span><span class="hljs-params">(String key, String value, <span class="hljs-type">long</span> timeout, TimeUnit unit)</span> &#123;<br>        redisTemplate.opsForValue().set(key, value, timeout, unit);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 只有在 key 不存在时设置 key 的值</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span> 之前已经存在返回false,不存在返回true</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">setIfAbsent</span><span class="hljs-params">(String key, String value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForValue().setIfAbsent(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 用 value 参数覆写给定 key 所储存的字符串值，从偏移量 offset 开始</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> offset</span><br><span class="hljs-comment">     *            从指定位置开始覆写</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setRange</span><span class="hljs-params">(String key, String value, <span class="hljs-type">long</span> offset)</span> &#123;<br>        redisTemplate.opsForValue().set(key, value, offset);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取字符串的长度</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">size</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForValue().size(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 批量添加</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> maps</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">multiSet</span><span class="hljs-params">(Map&lt;String, String&gt; maps)</span> &#123;<br>        redisTemplate.opsForValue().multiSet(maps);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 同时设置一个或多个 key-value 对，当且仅当所有给定 key 都不存在</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> maps</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span> 之前已经存在返回false,不存在返回true</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">multiSetIfAbsent</span><span class="hljs-params">(Map&lt;String, String&gt; maps)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForValue().multiSetIfAbsent(maps);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 增加(自增长), 负数则为自减</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">incrBy</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> increment)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForValue().increment(key, increment);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Double <span class="hljs-title function_">incrByFloat</span><span class="hljs-params">(String key, <span class="hljs-type">double</span> increment)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForValue().increment(key, increment);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 追加到末尾</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Integer <span class="hljs-title function_">append</span><span class="hljs-params">(String key, String value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForValue().append(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/** -------------------hash相关操作------------------------- */</span><br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取存储在哈希表中指定字段的值</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> field</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Object <span class="hljs-title function_">hGet</span><span class="hljs-params">(String key, String field)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForHash().get(key, field);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取所有给定字段的值</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Map&lt;Object, Object&gt; <span class="hljs-title function_">hGetAll</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForHash().entries(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取所有给定字段的值</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> fields</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> List&lt;Object&gt; <span class="hljs-title function_">hMultiGet</span><span class="hljs-params">(String key, Collection&lt;Object&gt; fields)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForHash().multiGet(key, fields);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">hPut</span><span class="hljs-params">(String key, String hashKey, String value)</span> &#123;<br>        redisTemplate.opsForHash().put(key, hashKey, value);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">hPutAll</span><span class="hljs-params">(String key, Map&lt;String, String&gt; maps)</span> &#123;<br>        redisTemplate.opsForHash().putAll(key, maps);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 仅当hashKey不存在时才设置</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> hashKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Boolean <span class="hljs-title function_">hPutIfAbsent</span><span class="hljs-params">(String key, String hashKey, String value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForHash().putIfAbsent(key, hashKey, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 删除一个或多个哈希表字段</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> fields</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">hDelete</span><span class="hljs-params">(String key, Object... fields)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForHash().delete(key, fields);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 查看哈希表 key 中，指定的字段是否存在</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> field</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">hExists</span><span class="hljs-params">(String key, String field)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForHash().hasKey(key, field);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 为哈希表 key 中的指定字段的整数值加上增量 increment</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> field</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> increment</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">hIncrBy</span><span class="hljs-params">(String key, Object field, <span class="hljs-type">long</span> increment)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForHash().increment(key, field, increment);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 为哈希表 key 中的指定字段的整数值加上增量 increment</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> field</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> delta</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Double <span class="hljs-title function_">hIncrByFloat</span><span class="hljs-params">(String key, Object field, <span class="hljs-type">double</span> delta)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForHash().increment(key, field, delta);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取所有哈希表中的字段</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;Object&gt; <span class="hljs-title function_">hKeys</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForHash().keys(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取哈希表中字段的数量</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">hSize</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForHash().size(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取哈希表中所有值</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> List&lt;Object&gt; <span class="hljs-title function_">hValues</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForHash().values(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 迭代哈希表中的键值对</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> options</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Cursor&lt;Entry&lt;Object, Object&gt;&gt; <span class="hljs-title function_">hScan</span><span class="hljs-params">(String key, ScanOptions options)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForHash().scan(key, options);<br>    &#125;<br><br>    <span class="hljs-comment">/** ------------------------list相关操作---------------------------- */</span><br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 通过索引获取列表中的元素</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> index</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">lIndex</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> index)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().index(key, index);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取列表指定范围内的元素</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> start</span><br><span class="hljs-comment">     *            开始位置, 0是开始位置</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> end</span><br><span class="hljs-comment">     *            结束位置, -1返回所有</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> List&lt;String&gt; <span class="hljs-title function_">lRange</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> start, <span class="hljs-type">long</span> end)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().range(key, start, end);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 存储在list头部</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">lLeftPush</span><span class="hljs-params">(String key, String value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().leftPush(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">lLeftPushAll</span><span class="hljs-params">(String key, String... value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().leftPushAll(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">lLeftPushAll</span><span class="hljs-params">(String key, Collection&lt;String&gt; value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().leftPushAll(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 当list存在的时候才加入</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">lLeftPushIfPresent</span><span class="hljs-params">(String key, String value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().leftPushIfPresent(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 如果pivot存在,再pivot前面添加</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> pivot</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">lLeftPush</span><span class="hljs-params">(String key, String pivot, String value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().leftPush(key, pivot, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">lRightPush</span><span class="hljs-params">(String key, String value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().rightPush(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">lRightPushAll</span><span class="hljs-params">(String key, String... value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().rightPushAll(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">lRightPushAll</span><span class="hljs-params">(String key, Collection&lt;String&gt; value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().rightPushAll(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 为已存在的列表添加值</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">lRightPushIfPresent</span><span class="hljs-params">(String key, String value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().rightPushIfPresent(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 在pivot元素的右边添加值</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> pivot</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">lRightPush</span><span class="hljs-params">(String key, String pivot, String value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().rightPush(key, pivot, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 通过索引设置列表元素的值</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> index</span><br><span class="hljs-comment">     *            位置</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">lSet</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> index, String value)</span> &#123;<br>        redisTemplate.opsForList().set(key, index, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 移出并获取列表的第一个元素</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span> 删除的元素</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">lLeftPop</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().leftPop(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 移出并获取列表的第一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> timeout</span><br><span class="hljs-comment">     *            等待时间</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> unit</span><br><span class="hljs-comment">     *            时间单位</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">lBLeftPop</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> timeout, TimeUnit unit)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().leftPop(key, timeout, unit);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 移除并获取列表最后一个元素</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span> 删除的元素</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">lRightPop</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().rightPop(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 移出并获取列表的最后一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> timeout</span><br><span class="hljs-comment">     *            等待时间</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> unit</span><br><span class="hljs-comment">     *            时间单位</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">lBRightPop</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> timeout, TimeUnit unit)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().rightPop(key, timeout, unit);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 移除列表的最后一个元素，并将该元素添加到另一个列表并返回</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> sourceKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destinationKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">lRightPopAndLeftPush</span><span class="hljs-params">(String sourceKey, String destinationKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,<br>                destinationKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 从列表中弹出一个值，将弹出的元素插入到另外一个列表中并返回它； 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> sourceKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destinationKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> timeout</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> unit</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">lBRightPopAndLeftPush</span><span class="hljs-params">(String sourceKey, String destinationKey,</span><br><span class="hljs-params">            <span class="hljs-type">long</span> timeout, TimeUnit unit)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,<br>                destinationKey, timeout, unit);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 删除集合中值等于value得元素</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> index</span><br><span class="hljs-comment">     *            index=0, 删除所有值等于value的元素; index&gt;0, 从头部开始删除第一个值等于value的元素;</span><br><span class="hljs-comment">     *            index&lt;0, 从尾部开始删除第一个值等于value的元素;</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">lRemove</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> index, String value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().remove(key, index, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 裁剪list</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> start</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> end</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">lTrim</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> start, <span class="hljs-type">long</span> end)</span> &#123;<br>        redisTemplate.opsForList().trim(key, start, end);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取列表长度</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">lLen</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForList().size(key);<br>    &#125;<br><br>    <span class="hljs-comment">/** --------------------set相关操作-------------------------- */</span><br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * set添加元素</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> values</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">sAdd</span><span class="hljs-params">(String key, String... values)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().add(key, values);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * set移除元素</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> values</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">sRemove</span><span class="hljs-params">(String key, Object... values)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().remove(key, values);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 移除并返回集合的一个随机元素</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">sPop</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().pop(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 将元素value从一个集合移到另一个集合</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Boolean <span class="hljs-title function_">sMove</span><span class="hljs-params">(String key, String value, String destKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().move(key, value, destKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取集合的大小</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">sSize</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().size(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 判断集合是否包含value</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Boolean <span class="hljs-title function_">sIsMember</span><span class="hljs-params">(String key, Object value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().isMember(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取两个集合的交集</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">sIntersect</span><span class="hljs-params">(String key, String otherKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().intersect(key, otherKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取key集合与多个集合的交集</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKeys</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">sIntersect</span><span class="hljs-params">(String key, Collection&lt;String&gt; otherKeys)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().intersect(key, otherKeys);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * key集合与otherKey集合的交集存储到destKey集合中</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">sIntersectAndStore</span><span class="hljs-params">(String key, String otherKey, String destKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().intersectAndStore(key, otherKey,<br>                destKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * key集合与多个集合的交集存储到destKey集合中</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKeys</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">sIntersectAndStore</span><span class="hljs-params">(String key, Collection&lt;String&gt; otherKeys,</span><br><span class="hljs-params">            String destKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().intersectAndStore(key, otherKeys,<br>                destKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取两个集合的并集</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKeys</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">sUnion</span><span class="hljs-params">(String key, String otherKeys)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().union(key, otherKeys);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取key集合与多个集合的并集</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKeys</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">sUnion</span><span class="hljs-params">(String key, Collection&lt;String&gt; otherKeys)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().union(key, otherKeys);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * key集合与otherKey集合的并集存储到destKey中</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">sUnionAndStore</span><span class="hljs-params">(String key, String otherKey, String destKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().unionAndStore(key, otherKey, destKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * key集合与多个集合的并集存储到destKey中</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKeys</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">sUnionAndStore</span><span class="hljs-params">(String key, Collection&lt;String&gt; otherKeys,</span><br><span class="hljs-params">            String destKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().unionAndStore(key, otherKeys, destKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取两个集合的差集</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">sDifference</span><span class="hljs-params">(String key, String otherKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().difference(key, otherKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取key集合与多个集合的差集</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKeys</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">sDifference</span><span class="hljs-params">(String key, Collection&lt;String&gt; otherKeys)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().difference(key, otherKeys);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * key集合与otherKey集合的差集存储到destKey中</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">sDifference</span><span class="hljs-params">(String key, String otherKey, String destKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().differenceAndStore(key, otherKey,<br>                destKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * key集合与多个集合的差集存储到destKey中</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKeys</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">sDifference</span><span class="hljs-params">(String key, Collection&lt;String&gt; otherKeys,</span><br><span class="hljs-params">            String destKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().differenceAndStore(key, otherKeys,<br>                destKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取集合所有元素</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">setMembers</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().members(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 随机获取集合中的一个元素</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">sRandomMember</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().randomMember(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 随机获取集合中count个元素</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> count</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> List&lt;String&gt; <span class="hljs-title function_">sRandomMembers</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> count)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().randomMembers(key, count);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 随机获取集合中count个元素并且去除重复的</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> count</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">sDistinctRandomMembers</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> count)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().distinctRandomMembers(key, count);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> options</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Cursor&lt;String&gt; <span class="hljs-title function_">sScan</span><span class="hljs-params">(String key, ScanOptions options)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForSet().scan(key, options);<br>    &#125;<br><br>    <span class="hljs-comment">/**------------------zSet相关操作--------------------------------*/</span><br>    <br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 添加元素,有序集合是按照元素的score值由小到大排列</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> score</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Boolean <span class="hljs-title function_">zAdd</span><span class="hljs-params">(String key, String value, <span class="hljs-type">double</span> score)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().add(key, value, score);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> values</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zAdd</span><span class="hljs-params">(String key, Set&lt;TypedTuple&lt;String&gt;&gt; values)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().add(key, values);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> values</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zRemove</span><span class="hljs-params">(String key, Object... values)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().remove(key, values);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 增加元素的score值，并返回增加后的值</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> delta</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Double <span class="hljs-title function_">zIncrementScore</span><span class="hljs-params">(String key, String value, <span class="hljs-type">double</span> delta)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().incrementScore(key, value, delta);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 返回元素在集合的排名,有序集合是按照元素的score值由小到大排列</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span> 0表示第一位</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zRank</span><span class="hljs-params">(String key, Object value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().rank(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 返回元素在集合的排名,按元素的score值由大到小排列</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zReverseRank</span><span class="hljs-params">(String key, Object value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().reverseRank(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取集合的元素, 从小到大排序</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> start</span><br><span class="hljs-comment">     *            开始位置</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> end</span><br><span class="hljs-comment">     *            结束位置, -1查询所有</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">zRange</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> start, <span class="hljs-type">long</span> end)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().range(key, start, end);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取集合元素, 并且把score值也获取</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> start</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> end</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;TypedTuple&lt;String&gt;&gt; <span class="hljs-title function_">zRangeWithScores</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> start,</span><br><span class="hljs-params">            <span class="hljs-type">long</span> end)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().rangeWithScores(key, start, end);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 根据Score值查询集合元素</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> min</span><br><span class="hljs-comment">     *            最小值</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> max</span><br><span class="hljs-comment">     *            最大值</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">zRangeByScore</span><span class="hljs-params">(String key, <span class="hljs-type">double</span> min, <span class="hljs-type">double</span> max)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().rangeByScore(key, min, max);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 根据Score值查询集合元素, 从小到大排序</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> min</span><br><span class="hljs-comment">     *            最小值</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> max</span><br><span class="hljs-comment">     *            最大值</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;TypedTuple&lt;String&gt;&gt; <span class="hljs-title function_">zRangeByScoreWithScores</span><span class="hljs-params">(String key,</span><br><span class="hljs-params">            <span class="hljs-type">double</span> min, <span class="hljs-type">double</span> max)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> min</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> max</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> start</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> end</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;TypedTuple&lt;String&gt;&gt; <span class="hljs-title function_">zRangeByScoreWithScores</span><span class="hljs-params">(String key,</span><br><span class="hljs-params">            <span class="hljs-type">double</span> min, <span class="hljs-type">double</span> max, <span class="hljs-type">long</span> start, <span class="hljs-type">long</span> end)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max,<br>                start, end);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取集合的元素, 从大到小排序</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> start</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> end</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">zReverseRange</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> start, <span class="hljs-type">long</span> end)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().reverseRange(key, start, end);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取集合的元素, 从大到小排序, 并返回score值</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> start</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> end</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;TypedTuple&lt;String&gt;&gt; <span class="hljs-title function_">zReverseRangeWithScores</span><span class="hljs-params">(String key,</span><br><span class="hljs-params">            <span class="hljs-type">long</span> start, <span class="hljs-type">long</span> end)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().reverseRangeWithScores(key, start,<br>                end);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 根据Score值查询集合元素, 从大到小排序</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> min</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> max</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">zReverseRangeByScore</span><span class="hljs-params">(String key, <span class="hljs-type">double</span> min,</span><br><span class="hljs-params">            <span class="hljs-type">double</span> max)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().reverseRangeByScore(key, min, max);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 根据Score值查询集合元素, 从大到小排序</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> min</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> max</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;TypedTuple&lt;String&gt;&gt; <span class="hljs-title function_">zReverseRangeByScoreWithScores</span><span class="hljs-params">(</span><br><span class="hljs-params">            String key, <span class="hljs-type">double</span> min, <span class="hljs-type">double</span> max)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key,<br>                min, max);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> min</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> max</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> start</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> end</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Set&lt;String&gt; <span class="hljs-title function_">zReverseRangeByScore</span><span class="hljs-params">(String key, <span class="hljs-type">double</span> min,</span><br><span class="hljs-params">            <span class="hljs-type">double</span> max, <span class="hljs-type">long</span> start, <span class="hljs-type">long</span> end)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().reverseRangeByScore(key, min, max,<br>                start, end);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 根据score值获取集合元素数量</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> min</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> max</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zCount</span><span class="hljs-params">(String key, <span class="hljs-type">double</span> min, <span class="hljs-type">double</span> max)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().count(key, min, max);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取集合大小</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zSize</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().size(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取集合大小</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zZCard</span><span class="hljs-params">(String key)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().zCard(key);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取集合中value元素的score值</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> value</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Double <span class="hljs-title function_">zScore</span><span class="hljs-params">(String key, Object value)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().score(key, value);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 移除指定索引位置的成员</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> start</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> end</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zRemoveRange</span><span class="hljs-params">(String key, <span class="hljs-type">long</span> start, <span class="hljs-type">long</span> end)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().removeRange(key, start, end);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 根据指定的score值的范围来移除成员</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> min</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> max</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zRemoveRangeByScore</span><span class="hljs-params">(String key, <span class="hljs-type">double</span> min, <span class="hljs-type">double</span> max)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().removeRangeByScore(key, min, max);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取key和otherKey的并集并存储在destKey中</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zUnionAndStore</span><span class="hljs-params">(String key, String otherKey, String destKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().unionAndStore(key, otherKey, destKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKeys</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zUnionAndStore</span><span class="hljs-params">(String key, Collection&lt;String&gt; otherKeys,</span><br><span class="hljs-params">            String destKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet()<br>                .unionAndStore(key, otherKeys, destKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 交集</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zIntersectAndStore</span><span class="hljs-params">(String key, String otherKey,</span><br><span class="hljs-params">            String destKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().intersectAndStore(key, otherKey,<br>                destKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 交集</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> otherKeys</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destKey</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Long <span class="hljs-title function_">zIntersectAndStore</span><span class="hljs-params">(String key, Collection&lt;String&gt; otherKeys,</span><br><span class="hljs-params">            String destKey)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().intersectAndStore(key, otherKeys,<br>                destKey);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * </span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> key</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> options</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> Cursor&lt;TypedTuple&lt;String&gt;&gt; <span class="hljs-title function_">zScan</span><span class="hljs-params">(String key, ScanOptions options)</span> &#123;<br>        <span class="hljs-keyword">return</span> redisTemplate.opsForZSet().scan(key, options);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="6-Redis配置文件详解"><a href="#6-Redis配置文件详解" class="headerlink" title="6 Redis配置文件详解"></a>6 Redis配置文件详解</h1><h1 id="6-1-容量单位"><a href="#6-1-容量单位" class="headerlink" title="6.1 容量单位"></a>6.1 容量单位</h1><p>不区分大小写，G和GB有区别</p>
<p><img src="https://img-blog.csdnimg.cn/2020051321485460.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload alt="img"></p>
<h2 id="6-2-使用多个配置"><a href="#6-2-使用多个配置" class="headerlink" title="6.2 使用多个配置"></a>6.2 使用多个配置</h2><p>使用 include 组合</p>
<p><img src="https://img-blog.csdnimg.cn/20200513214902552.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="6-3-网络配置"><a href="#6-3-网络配置" class="headerlink" title="6.3 网络配置"></a>6.3 网络配置</h2><p><img src="https://img-blog.csdnimg.cn/20200513214912813.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="6-4-通用GENERAL"><a href="#6-4-通用GENERAL" class="headerlink" title="6.4 通用GENERAL"></a>6.4 通用GENERAL</h2><p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831145932.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="6-5日志输出级别"><a href="#6-5日志输出级别" class="headerlink" title="6.5日志输出级别"></a>6.5日志输出级别</h2><p><img src="https://img-blog.csdnimg.cn/20200513214923678.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload alt="img"></p>
<h2 id="6-6-日志输出文件"><a href="#6-6-日志输出文件" class="headerlink" title="6.6 日志输出文件"></a>6.6 日志输出文件</h2><p><img src="https://img-blog.csdnimg.cn/20200513214933713.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="6-7-持久化规则-快照"><a href="#6-7-持久化规则-快照" class="headerlink" title="6.7 持久化规则(快照)"></a>6.7 持久化规则(快照)</h2><p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831145950.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p>持久化方式：</p>
<ul>
<li>RDB</li>
<li>AOF</li>
</ul>
<p><img src="https://img-blog.csdnimg.cn/20200513214944964.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="6-8-RDB文件相关"><a href="#6-8-RDB文件相关" class="headerlink" title="6.8 RDB文件相关"></a>6.8 RDB文件相关</h2><p><img src="https://img-blog.csdnimg.cn/20200513214955679.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p><img src="https://img-blog.csdnimg.cn/20200513215006207.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="6-9-安全"><a href="#6-9-安全" class="headerlink" title="6.9 安全"></a>6.9 安全</h2><p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831150009.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="6-10-限制"><a href="#6-10-限制" class="headerlink" title="6.10 限制"></a>6.10 限制</h2><p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831150030.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="6-11-APPEND-ONLY-模式-aof配置"><a href="#6-11-APPEND-ONLY-模式-aof配置" class="headerlink" title="6.11 APPEND ONLY 模式 aof配置"></a>6.11 APPEND ONLY 模式 aof配置</h2><p><img src="https://cdn.jsdelivr.net/gh/WSKH0929/images/20210831150045.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h1 id="7-redis持久化"><a href="#7-redis持久化" class="headerlink" title="7 redis持久化"></a>7 redis持久化</h1><h2 id="7-1-RDB"><a href="#7-1-RDB" class="headerlink" title="7.1 RDB"></a>7.1 RDB</h2><p>RDB：Redis Databases</p>
<h3 id="7-1-1-什么是RDB"><a href="#7-1-1-什么是RDB" class="headerlink" title="7.1.1 什么是RDB"></a>7.1.1 什么是RDB</h3><p>在指定时间间隔后，将内存中的数据集快照写入数据库 ；在恢复时候，直接读取快照文件，进行数据的恢复 ；</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215126515.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p>默认情况下， Redis 将数据库快照保存在名字为 dump.rdb的二进制文件中。文件名可以在配置文件中进行自定义。</p>
<h3 id="7-1-2-工作原理"><a href="#7-1-2-工作原理" class="headerlink" title="7.1.2 工作原理"></a>7.1.2 工作原理</h3><p>在进行 RDB 的时候，redis 的主线程是不会做 io 操作的，主线程会 fork 一个子线程来完成该操作；</p>
<ul>
<li><p>Redis 调用forks。同时拥有父进程和子进程。</p>
</li>
<li><p>子进程将数据集写入到一个临时 RDB 文件中。</p>
</li>
<li><p>当子进程完成对新 RDB 文件的写入时，Redis 用新 RDB 文件替换原来的 RDB 文件，并删除旧的 RDB 文件。</p>
</li>
</ul>
<p>这种工作方式使得 Redis 可以从写时复制（copy-on-write）机制中获益(因为是使用子进程进行写操作，而父进程依然可以接收来自客户端的请求。)</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215141519.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h3 id="7-1-3-触发机制"><a href="#7-1-3-触发机制" class="headerlink" title="7.1.3 触发机制"></a>7.1.3 触发机制</h3><ol>
<li>save的规则满足的情况下，会自动触发rdb原则</li>
<li>执行flushall命令，也会触发我们的rdb原则</li>
<li>退出redis，也会自动产生rdb文件</li>
</ol>
<p>使用 <code>save</code> 命令，会立刻对当前内存中的数据进行持久化 ,但是会阻塞，也就是不接受其他操作了；</p>
<p>由于 <code>save</code> 命令是同步命令，会占用Redis的主进程。若Redis数据非常多时，<code>save</code>命令执行速度会非常慢，阻塞所有客户端的请求。</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215150892.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p><code>flushall</code> 命令也会触发持久化 ；</p>
<p><code>bgsave</code> 是异步进行，进行持久化的时候，<code>redis</code> 还可以将继续响应客户端请求 ；</p>
<p><img src="https://img-blog.csdnimg.cn/2020051321523151.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p><strong>bgsave和save对比</strong></p>
<table>
<thead>
<tr>
<th>命令</th>
<th>save</th>
<th>bgsave</th>
</tr>
</thead>
<tbody><tr>
<td>IO类型</td>
<td>同步</td>
<td>异步</td>
</tr>
<tr>
<td>阻塞？</td>
<td>是</td>
<td>是（阻塞发生在fock()，通常非常快）</td>
</tr>
<tr>
<td>复杂度</td>
<td>O(n)</td>
<td>O(n)</td>
</tr>
<tr>
<td>优点</td>
<td>不会消耗额外的内存</td>
<td>不阻塞客户端命令</td>
</tr>
<tr>
<td>缺点</td>
<td>阻塞客户端命令</td>
<td>需要fock子进程，消耗内存</td>
</tr>
</tbody></table>
<p><strong>RDB优点：</strong></p>
<ol>
<li>适合大规模的数据恢复</li>
<li>对数据的完整性要求不高</li>
</ol>
<p><strong>RDB缺点：</strong></p>
<ol>
<li>需要一定的时间间隔进行操作，如果redis意外宕机了，这个最后一次修改的数据就没有了。</li>
<li>fork进程的时候，会占用一定的内容空间。</li>
</ol>
<h3 id="7-1-4-触发持久化规则"><a href="#7-1-4-触发持久化规则" class="headerlink" title="7.1.4 触发持久化规则"></a>7.1.4 触发持久化规则</h3><p>可以通过配置文件对 Redis 进行设置， 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时， 自动进行数据集保存操作。</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215205970.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p><img src="https://img-blog.csdnimg.cn/20200513215220858.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="7-2-AOF"><a href="#7-2-AOF" class="headerlink" title="7.2 AOF"></a>7.2 AOF</h2><p><strong>Append Only File</strong></p>
<p>将我们所有的命令都记录下来，history，恢复的时候就把这个文件全部再执行一遍</p>
<h3 id="7-2-1-什么是AOF"><a href="#7-2-1-什么是AOF" class="headerlink" title="7.2.1 什么是AOF"></a>7.2.1 什么是AOF</h3><p>以日志的形式来记录每个写的操作，将Redis执行过的所有指令记录下来（读操作不记录），只许追加文件但不可以改写文件，redis启动之初会读取该文件重新构建数据，换言之，redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。</p>
<p>快照功能（RDB）并不是非常耐久（durable）： 如果 Redis 因为某些原因而造成故障停机， 那么服务器将丢失最近写入、以及未保存到快照中的那些数据。 从 1.1 版本开始， Redis 增加了一种完全耐久的持久化方式： AOF 持久化。</p>
<p>如果要使用AOF，需要修改配置文件：<br><img src="https://img-blog.csdnimg.cn/20200513215247113.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p>appendonly no yes则表示启用AOF</p>
<p>默认是不开启的，我们需要手动配置，然后重启redis，就可以生效了！</p>
<p>如果这个aof文件有错位，这时候redis是启动不起来的，我需要修改这个aof文件</p>
<p>redis给我们提供了一个工具redis-check-aof –fix</p>
<h3 id="7-2-2-aof优缺点"><a href="#7-2-2-aof优缺点" class="headerlink" title="7.2.2 aof优缺点"></a>7.2.2 aof优缺点</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs bash">appendonly <span class="hljs-built_in">yes</span>  <span class="hljs-comment"># 默认是不开启aof模式的，默认是使用rdb方式持久化的，在大部分的情况下，rdb完全够用</span><br>appendfilename <span class="hljs-string">&quot;appendonly.aof&quot;</span><br><br><span class="hljs-comment"># appendfsync always # 每次修改都会sync 消耗性能</span><br>appendfsync everysec <span class="hljs-comment"># 每秒执行一次 sync 可能会丢失这一秒的数据</span><br><span class="hljs-comment"># appendfsync no # 不执行 sync ,这时候操作系统自己同步数据，速度最快</span><br></code></pre></td></tr></table></figure>

<p><strong>优点</strong></p>
<ol>
<li>每一次修改都会同步，文件的完整性会更加好</li>
<li>没秒同步一次，可能会丢失一秒的数据</li>
<li>从不同步，效率最高</li>
</ol>
<p><strong>缺点</strong></p>
<ol>
<li>相对于数据文件来说，aof远远大于rdb，修复速度比rdb慢！</li>
<li>Aof运行效率也要比rdb慢，所以我们redis默认的配置就是rdb持久化</li>
</ol>
<h2 id="7-3-RDB和AOF的对比和选择"><a href="#7-3-RDB和AOF的对比和选择" class="headerlink" title="7.3 RDB和AOF的对比和选择"></a>7.3 RDB和AOF的对比和选择</h2><table>
<thead>
<tr>
<th>RDB</th>
<th>AOF</th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>启动优先级</td>
<td>低</td>
<td>高</td>
</tr>
<tr>
<td>体积</td>
<td>小</td>
<td>大</td>
</tr>
<tr>
<td>恢复速度</td>
<td>快</td>
<td>慢</td>
</tr>
<tr>
<td>数据安全性</td>
<td>丢数据</td>
<td>根据策略决定</td>
</tr>
</tbody></table>
<h3 id="如何选择使用哪种持久化方式？"><a href="#如何选择使用哪种持久化方式？" class="headerlink" title="如何选择使用哪种持久化方式？"></a>如何选择使用哪种持久化方式？</h3><p>一般来说， 如果想达到足以媲美 PostgreSQL 的数据安全性， 你应该同时使用两种持久化功能。</p>
<p>如果你非常关心你的数据， 但仍然可以承受数分钟以内的数据丢失， 那么你可以只使用 RDB 持久化。</p>
<p>有很多用户都只使用 AOF 持久化， 但并不推荐这种方式： 因为定时生成 RDB 快照（snapshot）非常便于进行数据库备份， 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快。</p>
<h1 id="8-Redis发布和订阅"><a href="#8-Redis发布和订阅" class="headerlink" title="8 Redis发布和订阅"></a>8 Redis发布和订阅</h1><p>Redis 发布订阅(pub/sub)是一种消息通信模式：发送者(pub)发送消息，订阅者(sub)接收消息。</p>
<p>下图展示了频道 channel1 ， 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系：</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215523258.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p>当有新消息通过 PUBLISH 命令发送给频道 channel1 时， 这个消息就会被发送给订阅它的三个客户端：</p>
<p><img src="https://img-blog.csdnimg.cn/2020051321553483.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="8-1-相关命令"><a href="#8-1-相关命令" class="headerlink" title="8.1 相关命令"></a>8.1 相关命令</h2><table>
<thead>
<tr>
<th>命令</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>PSUBSCRIBE pattern [pattern..]</td>
<td>订阅一个或多个符合给定模式的频道。</td>
</tr>
<tr>
<td>PUNSUBSCRIBE pattern [pattern..]</td>
<td>退订一个或多个符合给定模式的频道。</td>
</tr>
<tr>
<td>PUBSUB subcommand [argument[argument]]</td>
<td>查看订阅与发布系统状态。</td>
</tr>
<tr>
<td>PUBLISH channel message</td>
<td>向指定频道发布消息</td>
</tr>
<tr>
<td>SUBSCRIBE channel [channel..]</td>
<td>订阅给定的一个或多个频道。</td>
</tr>
<tr>
<td>SUBSCRIBE channel [channel..]</td>
<td>退订一个或多个频道</td>
</tr>
</tbody></table>
<h2 id="8-2-实例"><a href="#8-2-实例" class="headerlink" title="8.2 实例"></a>8.2 实例</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs bash">------------订阅端----------------------<br>127.0.0.1:6379&gt; SUBSCRIBE sakura <span class="hljs-comment"># 订阅sakura频道</span><br>Reading messages... (press Ctrl-C to quit) <span class="hljs-comment"># 等待接收消息</span><br>1) <span class="hljs-string">&quot;subscribe&quot;</span> <span class="hljs-comment"># 订阅成功的消息</span><br>2) <span class="hljs-string">&quot;sakura&quot;</span><br>3) (<span class="hljs-built_in">integer</span>) 1<br>1) <span class="hljs-string">&quot;message&quot;</span> <span class="hljs-comment"># 接收到来自sakura频道的消息 &quot;hello world&quot;</span><br>2) <span class="hljs-string">&quot;sakura&quot;</span><br>3) <span class="hljs-string">&quot;hello world&quot;</span><br>1) <span class="hljs-string">&quot;message&quot;</span> <span class="hljs-comment"># 接收到来自sakura频道的消息 &quot;hello i am sakura&quot;</span><br>2) <span class="hljs-string">&quot;sakura&quot;</span><br>3) <span class="hljs-string">&quot;hello i am sakura&quot;</span><br><br>--------------消息发布端-------------------<br>127.0.0.1:6379&gt; PUBLISH sakura <span class="hljs-string">&quot;hello world&quot;</span> <span class="hljs-comment"># 发布消息到sakura频道</span><br>(<span class="hljs-built_in">integer</span>) 1<br>127.0.0.1:6379&gt; PUBLISH sakura <span class="hljs-string">&quot;hello i am sakura&quot;</span> <span class="hljs-comment"># 发布消息</span><br>(<span class="hljs-built_in">integer</span>) 1<br><br>-----------------查看活跃的频道------------<br>127.0.0.1:6379&gt; PUBSUB channels<br>1) <span class="hljs-string">&quot;sakura&quot;</span><br></code></pre></td></tr></table></figure>

<h2 id="8-3-原理"><a href="#8-3-原理" class="headerlink" title="8.3 原理"></a>8.3 原理</h2><p>每个 Redis 服务器进程都维持着一个表示服务器状态的 redis.h/redisServer 结构， 结构的 pubsub_channels 属性是一个字典， 这个字典就用于保存订阅频道的信息，其中，字典的键为正在被订阅的频道， 而字典的值则是一个链表， 链表中保存了所有订阅这个频道的客户端。<br><img src="https://img-blog.csdnimg.cn/2020051321554964.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p>客户端订阅，就被链接到对应频道的链表的尾部，退订则就是将客户端节点从链表中移除。</p>
<h2 id="8-4-缺点及应用"><a href="#8-4-缺点及应用" class="headerlink" title="8.4 缺点及应用"></a>8.4 缺点及应用</h2><p>缺点:<br>如果一个客户端订阅了频道，但自己读取消息的速度却不够快的话，那么不断积压的消息会使redis输出缓冲区的体积变得越来越大，这可能使得redis本身的速度变慢，甚至直接崩溃。<br>这和数据传输可靠性有关，如果在订阅方断线，那么他将会丢失所有在短线期间发布者发布的消息。<br>应用:<br>消息订阅：公众号订阅，微博关注等等（起始更多是使用消息队列来进行实现）<br>多人在线聊天室。<br>稍微复杂的场景，我们就会使用消息中间件MQ处理。</p>
<h1 id="9-主从复制"><a href="#9-主从复制" class="headerlink" title="9 主从复制"></a>9 主从复制</h1><h2 id="9-1-概念"><a href="#9-1-概念" class="headerlink" title="9.1 概念"></a>9.1 概念</h2><p>主从复制，是指将一台Redis服务器的数据，复制到其他的Redis服务器。前者称为主节点（Master/Leader）,后者称为从节点（Slave/Follower）， 数据的复制是单向的！只能由主节点复制到从节点（主节点以写为主、从节点以读为主）。默认情况下，每台Redis服务器都是主节点，一个主节点可以有0个或者多个从节点，但每个从节点只能由一个主节点。</p>
<h2 id="9-2-作用"><a href="#9-2-作用" class="headerlink" title="9.2 作用"></a>9.2 作用</h2><p><strong>数据冗余</strong>：主从复制实现了数据的热备份，是持久化之外的一种数据冗余的方式。<br><strong>故障恢复</strong>：当主节点故障时，从节点可以暂时替代主节点提供服务，是一种服务冗余的方式<br><strong>负载均衡</strong>：在主从复制的基础上，配合读写分离，由主节点进行写操作，从节点进行读操作，分担服务器的负载；尤其是在多读少写的场景下，通过多个从节点分担负载，提高并发量。<br><strong>高可用基石</strong>：主从复制还是哨兵和集群能够实施的基础。</p>
<h2 id="9-3-为什么使用集群"><a href="#9-3-为什么使用集群" class="headerlink" title="9.3 为什么使用集群"></a>9.3 为什么使用集群</h2><ol>
<li>单台服务器难以负载大量的请求</li>
<li>单台服务器故障率高，系统崩坏概率大</li>
<li>单台服务器内存容量有限。</li>
</ol>
<h2 id="9-4-环境配置"><a href="#9-4-环境配置" class="headerlink" title="9.4 环境配置"></a>9.4 环境配置</h2><p>我们在讲解配置文件的时候，注意到有一个<code>replication</code>模块 (见Redis.conf中第8条)</p>
<p>查看当前库的信息：<code>info replication</code></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs bash">127.0.0.1:6379&gt; info replication<br><span class="hljs-comment"># Replication</span><br>role:master <span class="hljs-comment"># 角色</span><br>connected_slaves:0 <span class="hljs-comment"># 从机数量</span><br>master_replid:3b54deef5b7b7b7f7dd8acefa23be48879b4fcff<br>master_replid2:0000000000000000000000000000000000000000<br>master_repl_offset:0<br>second_repl_offset:-1<br>repl_backlog_active:0<br>repl_backlog_size:1048576<br>repl_backlog_first_byte_offset:0<br>repl_backlog_histlen:0<br></code></pre></td></tr></table></figure>

<p>既然需要启动多个服务，就需要多个配置文件。每个配置文件对应修改以下信息：</p>
<ul>
<li>端口号</li>
<li>pid文件名</li>
<li>日志文件名</li>
<li>rdb文件名</li>
</ul>
<p>启动单机多服务集群：</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215610163.png" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="9-5-一主二从配置"><a href="#9-5-一主二从配置" class="headerlink" title="9.5  一主二从配置"></a>9.5  一主二从配置</h2><p>==默认情况下，每台Redis服务器都是主节点；==我们一般情况下只用配置从机就好了！</p>
<p>认老大！一主（79）二从（80，81）</p>
<p>使用<code>SLAVEOF host port</code>就可以为从机配置主机了。</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215637483.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p>然后主机上也能看到从机的状态：</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215645778.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p>我们这里是使用命令搭建，是暂时的，==真实开发中应该在从机的配置文件中进行配置，==这样的话是永久的。</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215654634.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="9-6-使用规则"><a href="#9-6-使用规则" class="headerlink" title="9.6 使用规则"></a>9.6 使用规则</h2><p>从机只能读，不能写，主机可读可写但是多用于写。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs bash"> 127.0.0.1:6381&gt; <span class="hljs-built_in">set</span> name sakura <span class="hljs-comment"># 从机6381写入失败</span><br>(error) READONLY You can<span class="hljs-string">&#x27;t write against a read only replica.</span><br><span class="hljs-string"></span><br><span class="hljs-string">127.0.0.1:6380&gt; set name sakura # 从机6380写入失败</span><br><span class="hljs-string">(error) READONLY You can&#x27;</span>t write against a <span class="hljs-built_in">read</span> only replica.<br><br>127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> name sakura<br>OK<br>127.0.0.1:6379&gt; get name<br><span class="hljs-string">&quot;sakura&quot;</span><br></code></pre></td></tr></table></figure>

<p>当主机断电宕机后，默认情况下从机的角色不会发生变化 ，集群中只是失去了写操作，当主机恢复以后，又会连接上从机恢复原状。</p>
<p>当从机断电宕机后，若不是使用配置文件配置的从机，再次启动后作为主机是无法获取之前主机的数据的，若此时重新配置称为从机，又可以获取到主机的所有数据。这里就要提到一个同步原理。</p>
<p>第二条中提到，默认情况下，主机故障后，不会出现新的主机，有两种方式可以产生新的主机：</p>
<p>从机手动执行命令<code>slaveof no one</code>,这样执行以后从机会独立出来成为一个主机<br>使用<strong>哨兵模式（自动选举）</strong></p>
<p>如果没有老大了，这个时候能不能选择出来一个老大呢？手动！</p>
<p>如果主机断开了连接，我们可以使用<code>SLAVEOF no one</code>让自己变成主机！其他的节点就可以手动连接到最新的主节点（手动）！如果这个时候老大修复了，那么久重新连接！</p>
<h1 id="10-哨兵模式"><a href="#10-哨兵模式" class="headerlink" title="10 哨兵模式"></a>10 哨兵模式</h1><p>更多信息参考博客：<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/06ab9daf921d">https://www.jianshu.com/p/06ab9daf921d</a></p>
<p>*<em>主从切换技术的方法是：当主服务器宕机后，需要手动把一台从服务器切换为主服务器，这就需要人工干预，费事费力，还会造成一段时间内服务不可用。</em>这不是一种推荐的方式，更多时候，我们优先考虑*哨兵模式。</p>
<h2 id="10-1-哨兵的作用："><a href="#10-1-哨兵的作用：" class="headerlink" title="10.1 哨兵的作用："></a>10.1 哨兵的作用：</h2><ul>
<li>通过发送命令，让Redis服务器返回监控其运行状态，包括主服务器和从服务器。</li>
<li>当哨兵监测到master宕机，会自动将slave切换成master，然后通过<strong>发布订阅模式</strong>通知其他的从服务器，修改配置文件，让它们切换主机。</li>
</ul>
<h2 id="10-2-哨兵的核心配置"><a href="#10-2-哨兵的核心配置" class="headerlink" title="10.2 哨兵的核心配置"></a>10.2 哨兵的核心配置</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">sentinel monitor mymaster 127.0.0.1 6379 1<br></code></pre></td></tr></table></figure>

<ul>
<li>数字1表示 ：当一个哨兵主观认为主机断开，就可以客观认为主机故障，然后开始选举新的主机。</li>
</ul>
<h2 id="10-3测试"><a href="#10-3测试" class="headerlink" title="10.3测试"></a>10.3测试</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">redis-sentinel xxx/sentinel.conf<br></code></pre></td></tr></table></figure>

<p>成功启动哨兵模式</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215752444.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p>此时哨兵监视着我们的主机6379，当我们断开主机后：</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215806972.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<h2 id="10-4-哨兵模式优缺点"><a href="#10-4-哨兵模式优缺点" class="headerlink" title="10.4 哨兵模式优缺点"></a>10.4 哨兵模式优缺点</h2><p><strong>优点：</strong></p>
<p>哨兵集群，基于主从复制模式，所有主从复制的优点，它都有<br>主从可以切换，故障可以转移，系统的可用性更好<br>哨兵模式是主从模式的升级，手动到自动，更加健壮<br><strong>缺点：</strong></p>
<p>Redis不好在线扩容，集群容量一旦达到上限，在线扩容就十分麻烦<br>实现哨兵模式的配置其实是很麻烦的，里面有很多配置项</p>
<h2 id="10-5-哨兵模式的全部配置"><a href="#10-5-哨兵模式的全部配置" class="headerlink" title="10.5 哨兵模式的全部配置"></a>10.5 哨兵模式的全部配置</h2><p>完整的哨兵模式配置文件 sentinel.conf</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># Example sentinel.conf</span><br> <br><span class="hljs-comment"># 哨兵sentinel实例运行的端口 默认26379</span><br>port 26379<br> <br><span class="hljs-comment"># 哨兵sentinel的工作目录</span><br><span class="hljs-built_in">dir</span> /tmp<br> <br><span class="hljs-comment"># 哨兵sentinel监控的redis主节点的 ip port </span><br><span class="hljs-comment"># master-name  可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符&quot;.-_&quot;组成。</span><br><span class="hljs-comment"># quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了</span><br><span class="hljs-comment"># sentinel monitor &lt;master-name&gt; &lt;ip&gt; &lt;redis-port&gt; &lt;quorum&gt;</span><br>sentinel monitor mymaster 127.0.0.1 6379 1<br> <br><span class="hljs-comment"># 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码</span><br><span class="hljs-comment"># 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码</span><br><span class="hljs-comment"># sentinel auth-pass &lt;master-name&gt; &lt;password&gt;</span><br>sentinel auth-pass mymaster MySUPER--secret-0123passw0rd<br> <br> <br><span class="hljs-comment"># 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒</span><br><span class="hljs-comment"># sentinel down-after-milliseconds &lt;master-name&gt; &lt;milliseconds&gt;</span><br>sentinel down-after-milliseconds mymaster 30000<br> <br><span class="hljs-comment"># 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步，</span><br>这个数字越小，完成failover所需的时间就越长，<br>但是如果这个数字越大，就意味着越 多的slave因为replication而不可用。<br>可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。<br><span class="hljs-comment"># sentinel parallel-syncs &lt;master-name&gt; &lt;numslaves&gt;</span><br>sentinel parallel-syncs mymaster 1<br> <br> <br> <br><span class="hljs-comment"># 故障转移的超时时间 failover-timeout 可以用在以下这些方面： </span><br><span class="hljs-comment">#1. 同一个sentinel对同一个master两次failover之间的间隔时间。</span><br><span class="hljs-comment">#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。</span><br><span class="hljs-comment">#3.当想要取消一个正在进行的failover所需要的时间。  </span><br><span class="hljs-comment">#4.当进行failover时，配置所有slaves指向新的master所需的最大时间。不过，即使过了这个超时，slaves依然会被正确配置为指向master，但是就不按parallel-syncs所配置的规则来了</span><br><span class="hljs-comment"># 默认三分钟</span><br><span class="hljs-comment"># sentinel failover-timeout &lt;master-name&gt; &lt;milliseconds&gt;</span><br>sentinel failover-timeout mymaster 180000<br> <br><span class="hljs-comment"># SCRIPTS EXECUTION</span><br> <br><span class="hljs-comment">#配置当某一事件发生时所需要执行的脚本，可以通过脚本来通知管理员，例如当系统运行不正常时发邮件通知相关人员。</span><br><span class="hljs-comment">#对于脚本的运行结果有以下规则：</span><br><span class="hljs-comment">#若脚本执行后返回1，那么该脚本稍后将会被再次执行，重复次数目前默认为10</span><br><span class="hljs-comment">#若脚本执行后返回2，或者比2更高的一个返回值，脚本将不会重复执行。</span><br><span class="hljs-comment">#如果脚本在执行过程中由于收到系统中断信号被终止了，则同返回值为1时的行为相同。</span><br><span class="hljs-comment">#一个脚本的最大执行时间为60s，如果超过这个时间，脚本将会被一个SIGKILL信号终止，之后重新执行。</span><br> <br><span class="hljs-comment">#通知型脚本:当sentinel有任何警告级别的事件发生时（比如说redis实例的主观失效和客观失效等等），将会去调用这个脚本，</span><br><span class="hljs-comment">#这时这个脚本应该通过邮件，SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时，将传给脚本两个参数，</span><br><span class="hljs-comment">#一个是事件的类型，</span><br><span class="hljs-comment">#一个是事件的描述。</span><br><span class="hljs-comment">#如果sentinel.conf配置文件中配置了这个脚本路径，那么必须保证这个脚本存在于这个路径，并且是可执行的，否则sentinel无法正常启动成功。</span><br><span class="hljs-comment">#通知脚本</span><br><span class="hljs-comment"># sentinel notification-script &lt;master-name&gt; &lt;script-path&gt;</span><br>  sentinel notification-script mymaster /var/redis/notify.sh<br> <br><span class="hljs-comment"># 客户端重新配置主节点参数脚本</span><br><span class="hljs-comment"># 当一个master由于failover而发生改变时，这个脚本将会被调用，通知相关的客户端关于master地址已经发生改变的信息。</span><br><span class="hljs-comment"># 以下参数将会在调用脚本时传给脚本:</span><br><span class="hljs-comment"># &lt;master-name&gt; &lt;role&gt; &lt;state&gt; &lt;from-ip&gt; &lt;from-port&gt; &lt;to-ip&gt; &lt;to-port&gt;</span><br><span class="hljs-comment"># 目前&lt;state&gt;总是“failover”,</span><br><span class="hljs-comment"># &lt;role&gt;是“leader”或者“observer”中的一个。 </span><br><span class="hljs-comment"># 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的</span><br><span class="hljs-comment"># 这个脚本应该是通用的，能被多次调用，不是针对性的。</span><br><span class="hljs-comment"># sentinel client-reconfig-script &lt;master-name&gt; &lt;script-path&gt;</span><br>sentinel client-reconfig-script mymaster /var/redis/reconfig.sh<br></code></pre></td></tr></table></figure>

<h1 id="11-缓存穿透和雪崩"><a href="#11-缓存穿透和雪崩" class="headerlink" title="11 缓存穿透和雪崩"></a>11 缓存穿透和雪崩</h1><h2 id="11-1-缓存穿透"><a href="#11-1-缓存穿透" class="headerlink" title="11.1 缓存穿透"></a>11.1 缓存穿透</h2><p><strong>概念</strong></p>
<p>在默认情况下，用户请求数据时，会先在缓存(Redis)中查找，若没找到即缓存未命中，再在数据库中进行查找，数量少可能问题不大，可是一旦大量的请求数据（例如秒杀场景）缓存都没有命中的话，就会全部转移到数据库上，造成数据库极大的压力，就有可能导致数据库崩溃。网络安全中也有人恶意使用这种手段进行攻击被称为洪水攻击。</p>
<p><strong>缓存穿透的解决方案:</strong></p>
<p>1.<strong>布隆过滤器</strong></p>
<p>对所有可能查询的参数以Hash的形式存储，以便快速确定是否存在这个值，在控制层先进行拦截校验，校验不通过直接打回，减轻了存储系统的压力。</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215824722.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p>2.<strong>缓存空对象</strong></p>
<p>一次请求若在缓存和数据库中都没找到，就在缓存中方一个空对象用于处理后续这个请求。</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215836317.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p>这样做有一个缺陷：存储空对象也需要空间，大量的空对象会耗费一定的空间，存储效率并不高。解决这个缺陷的方式就是设置较短过期时间</p>
<p>即使对空值设置了过期时间，还是会存在缓存层和存储层的数据会有一段时间窗口的不一致，这对于需要保持一致性的业务会有影响。</p>
<h2 id="11-2-缓存击穿"><a href="#11-2-缓存击穿" class="headerlink" title="11.2 缓存击穿"></a>11.2 缓存击穿</h2><p><strong>概念</strong></p>
<p>相较于缓存穿透，缓存击穿的目的性更强，一个存在的key，在缓存过期的一刻，同时有大量的请求，这些请求都会击穿到DB，造成瞬时DB请求量大、压力骤增。这就是缓存被击穿，只是针对其中某个key的缓存不可用而导致击穿，但是其他的key依然可以使用缓存响应。</p>
<p> 比如热搜排行上，一个热点新闻被同时大量访问就可能导致缓存击穿。</p>
<p><strong>解决方案</strong></p>
<p><strong>1.设置热点数据永不过期</strong></p>
<p>这样就不会出现热点数据过期的情况，但是当Redis内存空间满的时候也会清理部分数据，而且此种方案会占用空间，一旦热点数据多了起来，就会占用部分空间。</p>
<p><strong>2.加互斥锁(分布式锁)</strong></p>
<p>在访问key之前，采用SETNX（set if not exists）来设置另一个短期key来锁住当前key的访问，访问结束再删除该短期key。保证同时刻只有一个线程访问。这样对锁的要求就十分高。</p>
<h2 id="11-3-缓存雪崩"><a href="#11-3-缓存雪崩" class="headerlink" title="11.3 缓存雪崩"></a>11.3 缓存雪崩</h2><p><strong>概念</strong></p>
<p>大量的key设置了相同的过期时间，导致在缓存在同一时刻全部失效，造成瞬时DB请求量大、压力骤增，引起雪崩。</p>
<p><img src="https://img-blog.csdnimg.cn/20200513215850428.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg3MzIyNw==,size_16,color_FFFFFF,t_70" srcset="/my-hexo-fluid/img/loading.gif" lazyload></p>
<p><strong>解决方案</strong></p>
<ul>
<li>redis高可用</li>
</ul>
<p>这个思想的含义是，既然redis有可能挂掉，那我多增设几台redis，这样一台挂掉之后其他的还可以继续工作，其实就是搭建的集群</p>
<ul>
<li>限流降级</li>
</ul>
<p>这个解决方案的思想是，在缓存失效后，通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存，其他线程等待。</p>
<ul>
<li>数据预热</li>
</ul>
<p>数据加热的含义就是在正式部署之前，我先把可能的数据先预先访问一遍，这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key，设置不同的过期时间，让缓存失效的时间点尽量均匀。</p>
<h1 id="12-学习链接"><a href="#12-学习链接" class="headerlink" title="12 学习链接"></a>12 学习链接</h1><p>参考链接：<a target="_blank" rel="noopener" href="https://blog.csdn.net/DDDDeng_/article/details/108118544?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163032815816780261933185%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=163032815816780261933185&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-108118544.first_rank_v2_pc_rank_v29&amp;utm_term=redis%E7%8B%82%E7%A5%9E%E8%AF%B4%E7%AC%94%E8%AE%B0&amp;spm=1018.2226.3001.4187">https://blog.csdn.net/DDDDeng_/article/details/108118544?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163032815816780261933185%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&amp;request_id=163032815816780261933185&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-108118544.first_rank_v2_pc_rank_v29&amp;utm_term=redis%E7%8B%82%E7%A5%9E%E8%AF%B4%E7%AC%94%E8%AE%B0&amp;spm=1018.2226.3001.4187</a></p>
<p>狂神视频链接：<a target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1S54y1R7SB?p=36">https://www.bilibili.com/video/BV1S54y1R7SB?p=36</a></p>

                
              </div>
            
            <hr/>
            <div>
              <div class="post-metas my-3">
  
    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>
      

<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/my-hexo-fluid/categories/%E5%90%8E%E7%AB%AF/" class="category-chain-item">后端</a>
  
  

      </span>
    
  
</span>

    </div>
  
  
    <div class="post-meta">
      <i class="iconfont icon-tags"></i>
      
        <a href="/my-hexo-fluid/tags/KuangShen/">#KuangShen</a>
      
        <a href="/my-hexo-fluid/tags/Java/">#Java</a>
      
        <a href="/my-hexo-fluid/tags/Redis/">#Redis</a>
      
    </div>
  
</div>


              
  

  <div class="license-box my-3">
    <div class="license-title">
      <div>Redis进阶-狂神笔记</div>
      <div>https://wskh0929.gitee.io/2023/01/01/Redis进阶-狂神笔记/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div>WSKH0929</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2023年1月1日</div>
        </div>
      
      
      
        <div class="license-meta-item">
          <div>许可协议</div>
          <div>
            
              
              
                <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
                  <span class="hint--top hint--rounded" aria-label="BY - 署名">
                    <i class="iconfont icon-by"></i>
                  </span>
                </a>
              
            
          </div>
        </div>
      
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/my-hexo-fluid/2023/01/01/R-language-visualization/" title="R language visualization">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">R language visualization</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/my-hexo-fluid/2022/12/30/hello-world/" title="Hello World">
                        <span class="hidden-mobile">Hello World</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
  
  
    <article id="comments" lazyload>
      
  <div id="valine"></div>
  <script type="text/javascript">
    Fluid.utils.loadComments('#valine', function() {
      Fluid.utils.createScript('https://lib.baomitu.com/valine/1.5.1/Valine.min.js', function() {
        var options = Object.assign(
          {"appId":"jkBkMZcW6P8K0bQScoJqvQrX-9Nh9j0Va","appKey":"1k6toLLZa7DFnrENpqSs9Ouw","path":"window.location.pathname","placeholder":"留言仅限讨论，禁止广告等行为","avatar":"retro","meta":["nick","mail","link"],"requiredFields":[],"pageSize":10,"lang":"zh-CN","highlight":false,"recordIP":false,"serverURLs":"https://jkbkmzcw.lc-cn-e1-shared.com","emojiCDN":null,"emojiMaps":null,"enableQQ":false},
          {
            el: "#valine",
            path: window.location.pathname
          }
        )
        new Valine(options);
        Fluid.utils.waitElementVisible('#valine .vcontent', () => {
          var imgSelector = '#valine .vcontent img:not(.vemoji)';
          Fluid.plugins.imageCaption(imgSelector);
          Fluid.plugins.fancyBox(imgSelector);
        })
      });
    });
  </script>
  <noscript>Please enable JavaScript to view the comments</noscript>


    </article>
  


          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header">
    <i class="iconfont icon-list"></i>
    <span>目录</span>
  </p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>





  



  



  



  



  







    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
    </div>
  
  
    <div class="statistics">
  
  

  
    
      <span id="busuanzi_container_site_pv" style="display: none">
        总访问量 
        <span id="busuanzi_value_site_pv"></span>
         次
      </span>
    
    
      <span id="busuanzi_container_site_uv" style="display: none">
        总访客数 
        <span id="busuanzi_value_site_uv"></span>
         人
      </span>
    
    
  
</div>

  
  
  
</div>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/my-hexo-fluid/js/events.js" ></script>
<script  src="/my-hexo-fluid/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>




  
    <script  src="/my-hexo-fluid/js/img-lazyload.js" ></script>
  




  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init(Object.assign({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      scrollSmooth    : true,
      includeTitleTags: true,
      headingsOffset  : -boardTop,
    }, CONFIG.toc));
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }

    Fluid.events.registerRefreshCallback(function() {
      if ('tocbot' in window) {
        tocbot.refresh();
        var toc = jQuery('#toc');
        if (toc.length === 0 || !tocbot) {
          return;
        }
        if (toc.find('.toc-list-item').length > 0) {
          toc.css('visibility', 'visible');
        }
      }
    });
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.11/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));

    Fluid.events.registerRefreshCallback(function() {
      if ('anchors' in window) {
        anchors.removeAll();
        var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
        var res = [];
        for (var item of el) {
          res.push('.markdown-body > ' + item.trim());
        }
        if (CONFIG.anchorjs.placement === 'left') {
          anchors.options.class = 'anchorjs-link-left';
        }
        anchors.add(res.join(', '));
      }
    });
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/my-hexo-fluid/js/local-search.js" ></script>

  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>




  
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/love.js"></script>
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/xiaoxingxing.js"></script>
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/xiaoxuehua.js"></script>
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/caidai.js"></script>



<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/my-hexo-fluid/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
</body>
</html>
